使用React钩子来防止D3图表的React重新呈现

时间:2019-12-12 10:43:39

标签: reactjs d3.js react-hooks

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

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

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

包装代码:

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;

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

挂钩版本:

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组件。

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

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

1 个答案:

答案 0 :(得分:0)

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

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