如何在React中控制非反应组件(BokehJS)?

时间:2019-05-03 14:40:31

标签: reactjs bokeh bokehjs

背景故事
我想在我的React组件中包含一个BokehJS图。此过程是呈现<div id="my_plot_id" className="bk-root"/>并调用window.Bokeh.embed.embed_item(plotData, 'my_plot_id'),这会将所需的HTML注入DOM。

因为我想使用React组件的状态来控制BokehJS图(即用新生成的图数据替换图),所以我不想只在embed_item()中调用componentDidMount()。我将embed_item()放在render()中,并在此调用之前添加了一些代码来删除容器div的子节点。

问题
我的React组件在页面加载时渲染3次,尽管到最后一次渲染,我只显示了一个图,但是有一小段时间(我认为在第二和第三/最终渲染之间),我可以看到两个图。

代码

render()
  {
    let plotNode = document.getElementById('my_plot_id');    
    console.log(plotNode && plotNode.childElementCount);

    while (plotNode && plotNode.firstChild) {
      //remove any children
      plotNode.removeChild(plotNode.firstChild);
    }

    const { plotData } = this.state;
    window.Bokeh.embed.embed_item(plotData, 'my_plot_id');

    return(
      <div id="my_plot_id" className="bk-root"/>
    )
  }

在控制台中,我看到:

  


  0
  2

问题
因此,在正确检测到embed_item子级之前,似乎my_plot_id执行了两次。

为什么会发生这种情况,我该如何解决?虽然三重渲染可能无法优化性能,但我认为我的组件应该能够(在合理的范围内)按需要进行多次重新渲染,而不会出现类似的视觉故障,因此我并未将思想集中在防止重新渲染上。渲染。

2 个答案:

答案 0 :(得分:0)

与DOM元素的交互应该从不发生在render方法内部。您应该使用生命周期方法componentDidMount在元素上启动库,使用componentDidUpdate根据道具更新它,并使用componentWillUnmount销毁它。

official React documentation有一个使用jQuery的示例,向您展示了如何处理其他dom库的要点。

答案 1 :(得分:0)

开始时plotNode无法到达'my_plot_id'

null不可用时,您可以在开始时渲染plotData

您可以使用componentDidUpdate()

在这种情况下,我将尝试shouldComponentUpdate()-更新DOM节点并返回false以避免重新呈现。