使用React钩子来防止D3图表的React重新呈现 [英] Using React hooks to prevent React re-rendering of a D3 chart

查看:50
本文介绍了使用React钩子来防止D3图表的React重新呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在分别使用React和D3,现在有一个项目需要对应用程序的绘图功能进行低级控制.基本上,我需要能够在用户放大图时从数据库中获取更高分辨率的数据,反之亦然在用户放大图时从数据库中获取更高分辨率的数据.

I have been using React and D3 separately and now have a project where I need low level control over the plotting function of an application. Basically, I need to be able to go and fetch higher resolution data from a database as the user zooms in, and vice versa as the user zooms out, on a plot.

我发现了几种同时使用D3和React的方法.我想尝试使我的所有React代码都基于hooks API,因为这是其余代码库所使用的.我正在努力使自己面对的特定情况变得与众不同.关于React钩子的文档很棒,但是我认为我的情况更多是处于边缘情况,并且我还没有看到任何与类似用例有关的讨论.

I have found a few methods to use D3 and React together. I wanted to try and keep all of my React code based around the hooks API as that is what is used for the rest of the code base. I am struggling to get the hooks equivalent for the specific cases that I am facing. The documentation on React hooks is great but I think my situation is more of an edge case and I have not seen any discussion relating to similar use cases to what I have.

代码的逻辑非常简单:我有一个主容器,称为App.js,它具有某种状态.App.js呈现一个Wrapper组件(正在发生挑战),然后Wrapper.js文件仅创建D3绘图.D3图只是具有某些缩放事件的线图的典型D3代码.

The logic of the code is fairly straight forward: I have a main container, call it App.js, that hold some state. App.js renders a Wrapper component (which is where the challenge is occurring) and then the Wrapper.js file simply creates the D3 Plot. The D3 plot is just typical D3 code for a line plot with some zoom events.

包装器代码:

import React, { Component } from 'react';
import Plot from './Plot'; // D3 plot

class Wrapper extends Component {

    // Sets up plot when Wrapper first added to DOM tree
    componentDidMount(){
        this.setState({
            plot: new Plot(this.refs.plot, this.props.data, this.props.updateData)
        });
    };

    // Do not allow React to re-render the Wrapper and therefore the Plot
    shouldComponentUpdate(){
        return false;
    };

    // When the data prop changes, execute the update() method in the plot file
    componentWillReceiveProps(nextProps){
        this.state.plot.update(nextProps.data) // the .update() method calls props.updateData()
    }

    render(){
        return <div ref="plot"></div>
    }
}

export default Wrapper;

我已经开始将下面的钩子版本放在一起,但是我无法提出合适的方法来满足我对shouldComponentUpdate和componentWIllReceiveProps块的具体要求.

I have started putting together the hooks version below but I cannot come up with suitable emthods that meet the specific requirements of what I am after for the cases of the shouldComponentUpdate and componentWIllReceiveProps blocks.

挂钩版本:

import React, { useEffect, useRef } from 'react';
import Plot from './Plot'; // D3 plot

const Wrapper = props => {

    // destruct props
    const { 
        data = props.data,
        fields = props.fields,
        click = props.click
    } = props

    // initialise empty ref
    const plotRef= useRef(null);

    // ComponentDidMount translated to hooks
    useEffect(() => {
        new Plot(plotRef, data, updateData)
    },[]) // empty array ensures the plot object is only created once on initial mounting

    // shouldComponentUpdate
    useEffect(...) // This won't work because render has already occurred before useEffect dependency array diffed?

    // ComponentWIllReceiveProps
    useEffect(() => {
        plot.update(data)
    }, [data]) // This won't work because component needs to have re-rendered

    return (
        <div ref= {plotRef}></div>
    )


};

export default Wrapper;

我要实现的目标是在初始安装后阻止D3图表的任何渲染,但是如果数据属性在父组件中发生了变化,请在D3类中执行一个方法,而不允许React重新渲染Wrapper组件.

What I am trying to achieve is blocking any rendering of the D3 chart after the initial mount, but then if the data props changes in the parent component, execute a method in the D3 class without allowing React to re-render the Wrapper component.

这是完全可能的还是我最好还是将其作为基于类的组件?

Is this at all possible or am I better off leaving this as a class based component?

我一直在撞墙,试图获得没有成功的逻辑,因此将不胜感激.

I have been banging my head against a wall trying to get the logic without any success so any input would be greatly appreciated.

推荐答案

您可以使用适当的依赖关系将返回值包装在React useMemo中.

you can wrap your return value in React useMemo with suitable dependencies.

https://reactjs.org/docs/hooks-reference.html#usememo

这篇关于使用React钩子来防止D3图表的React重新呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆