父状态更改后在React上强制重新渲染D3组件

时间:2018-10-03 00:30:32

标签: javascript reactjs typescript d3.js

我有两个反应成分(在打字稿中)。在第一个组件中,我有一些菜单。

   <Menu.Item
      name="graph"
      active={activeItem === "graph"}
      onClick={this.handleItemClick}
    />
    <Menu.Item
      name="flow"
      active={activeItem === "flow"}
      onClick={this.handleItemClick}
    />

相应的事件处理程序

handleItemClick = (e, { name }) => {this.setState({ activeItem: name, hello: name, selection:name });};

在render函数中,我将此决定作为属性传递给另一个React组件D3Core

返回之前,

var child = this.state.selection==="graph"? true : false ;

内部收益

<D3Core renderfull = {child} width={this.state.width} height={this.state.height} data={data} />

在D3Core渲染功能中,我正在使用以下内容渲染图形

if(this.props.renderfull) {
        return <div style={style} ref={mountPoint => (this.ctrls.mountPoint = mountPoint)} />;
    } else {
        return <p>Hello</p>;
    }

其中,强制布局d3的计算是在componentDidMount回调内部完成的。

componentDidMount() {
    const { width, height, data } = this.props;
    const force = d3
      .forceSimulation()
      .nodes(data.nodes)
      .force('charge', d3.forceManyBody().strength(-120))
      .force('link', d3.forceLink(data.links).distance(50))
      .force('center', d3.forceCenter(width / 2, height / 2));

const svg = d3
      .select(this.ctrls.mountPoint)
      .append('svg')
      .attr('width', width)
      .attr('height', height);
    ...

我面临的问题是,当我第一次加载文档时它会显示图形,但是如果我离开菜单并返回菜单,它将仅加载div而不是图形。我想我必须重新渲染图形,但是如何?

我猜这是因为所有组件都已经渲染,而d3计算根本没有发生。我应该在render内部进行计算吗?

我附上了几个屏幕截图。第一张屏幕截图显示了首次加载页面时呈现的图形。第二张屏幕截图显示,当我离开图形菜单并返回时,该图形不仅呈现为div元素。

编辑1:Here是我的d3代码

enter image description here enter image description here

1 个答案:

答案 0 :(得分:2)

我认为问题在于,renderfull被关闭然后再次打开时,React从文档中删除了旧的div并添加了一个新的{D1}实例,并且您的D3实例仍附加到旧(已移除)div。但是,D3Core组件实例始终保持挂载状态,因此您不会收到新的componentDidMount回调。

最干净的解决方案是将D3内容移动到D3Core的子组件中(例如,假设子组件名为D3Sub),并使用D3Core的{​​{1} }方法只有在render为真时才返回<D3Sub ...>。然后,当renderfull被关闭并再次打开时,renderfull实例将被销毁并创建一个新的D3Sub实例,新实例将获得一个{{1} }回调。