背景故事
我想在我的 React 组件中包含 BokehJS 图。这样做的过程是呈现<div id="my_plot_id" className="bk-root"/>
并调用window.Bokeh.embed.embed_item(plotData, 'my_plot_id')
,将所需的HTML注入DOM中。
因为我想使用 React 组件的状态来控制 BokehJS 图(即用新生成的图数据替换图),所以我不想只在componentDidMount()
中调用embed_item()
。相反,我将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 阿拉伯数字
问题
因此,在正确检测到my_plot_id
子项之前embed_item
似乎执行了两次。
为什么会发生这种情况,我该如何解决?虽然三重渲染可能没有优化性能,但我相信我的组件应该能够根据需要(在合理范围内)重新渲染,而不会像这样出现视觉故障,所以我没有把注意力集中在防止重新渲染的方法上。
与 DOM 元素的交互不应该发生在render
方法中。您应该使用生命周期方法componentDidMount
在元素上启动库,使用componentDidUpdate
根据 props 更新它并使用componentWillUnmount
销毁它。
官方的 React 文档有一个使用 jQuery 的示例,它向您展示了如何处理其他 dom 库的要点。
开始时plotNode
无法到达'my_plot_id'
。
您可以在开始时plotData
不可用时呈现null
。
您可以使用componentDidUpdate()
.
在这种情况下,我会尝试shouldComponentUpdate()
- 更新 DOM 节点并返回false
以避免重新渲染。