【问题标题】:Using React hooks to prevent React re-rendering of a D3 chart使用 React 钩子防止 React 重新渲染 D3 图表
【发布时间】:2019-12-12 10:43:39
【问题描述】:

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

我找到了一些同时使用 D3 和 React 的方法。我想尝试保留所有基于 hooks API 的 React 代码,因为这是用于其余代码库的内容。我正在努力为我所面临的特定情况获得等效的钩子。 React hooks 的文档很棒,但我认为我的情况更像是一个边缘案例,我还没有看到任何与我所拥有的类似用例相关的讨论。

代码的逻辑相当简单: 我有一个主容器,叫它 App.js,它持有一些状态。 App.js 呈现一个 Wrapper 组件(这是发生挑战的地方),然后 Wrapper.js 文件简单地创建 D3 Plot。 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;

我已经开始整理下面的钩子版本,但是对于 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组件。

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

我一直在用头撞墙,试图获得逻辑但没有任何成功,因此非常感谢任何输入。

【问题讨论】:

    标签: reactjs d3.js react-hooks


    【解决方案1】:

    你可以用合适的依赖将你的返回值包装在 React useMemo 中。

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

    【讨论】:

    • 感谢您的回复。您的意思是将 Wrapper 包装在 useMemo 中,然后只有一个空白的依赖数组以避免重新渲染?在那种情况下,我想知道 React.Memo 是不是更好的选择?
    • 是的,但你告诉过你想在重新渲染时运行一些函数。如果你使用 React.memo 整个组件将不会被调用。如果你使用 useMemo ,那里面的东西就不会被调用,所有其他的函数都会被调用。
    猜你喜欢
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-26
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    相关资源
    最近更新 更多