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

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

问题描述

我一直单独使用 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 结合使用的方法.我想尝试保留基于 hooks API 的所有 React 代码,因为它用于其余代码库.我正在努力为我面临的特定情况获得等效的钩子.React hooks 的文档很棒,但我认为我的情况更像是一种边缘情况,我没有看到任何与我所拥有的类似用例相关的讨论.

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 Plot.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 钩子防止 React 重新渲染 D3 图表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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