如何从非React的D3渲染函数调用React组件的contextmenu方法?
首先咱们拆解下核心问题:你需要在独立的renderTree函数里触发React组件的contextmenu方法,之前的问题出在没有把React组件的方法正确传递给D3的事件回调,同时renderTree的参数写法也存在错误。下面给你两种可行的解决方案:
方案一:直接传递React组件的contextmenu方法(推荐)
这是最简洁可靠的方式,不需要依赖refs,步骤如下:
- 修正componentDidMount中的调用逻辑
在组件挂载时,把绑定好this的contextmenu方法作为参数传给renderTree,确保方法执行时的上下文是React组件实例:
componentDidMount() { var mountNode = ReactDom.findDOMNode(this.tree); if (this.props.treeData) { // 传入绑定了组件this的contextmenu方法 renderTree(this.props.treeData, mountNode, this.props.nodeName, this.contextmenu.bind(this)); } }
- 修改renderTree的参数与事件绑定
先修正renderTree的参数定义(原来的this.props.treeData写法不符合函数参数规范),然后在D3的点击事件中直接调用传入的方法:
function renderTree(treeData, mountNode, nodeName, handleContextMenu) { // 你的D3树渲染逻辑... .on('click', handleContextMenu); // 直接调用传入的React组件方法 }
- 修复contextmenu方法的setState写法
注意你原来的setState是错误的赋值写法,setState是React组件的方法,需要通过调用的方式更新状态:
contextmenu(node) { this.setState({ style_popup: { top: d3.event.clientY, left: d3.event.clientX, position: 'absolute' }, render_on_click: true }); }
方案二:正确使用refs获取子组件实例
如果你坚持要用refs的方式,需要确保父组件能正确拿到子组件的实例:
- 确认子组件的导出方式
比如在D3Tree组件文件中是默认导出:
export default D3Tree;
- 父组件中正确获取ref
ref的赋值是异步的,要在组件挂载完成后才能访问到实例,比如在componentDidMount中:
class ParentComponent extends React.Component { componentDidMount() { // 此时子组件已挂载,可以访问this.D3tree console.log(this.D3tree); } render() { return ( <D3Tree ref={instance => { this.D3tree = instance; }} treeData={this.props.treeData} /> ); } }
之后如果需要在renderTree中调用组件的contextmenu,可以通过子组件实例的方法触发,但这种方式不如参数传递直接,还需要注意ref的生命周期问题。
内容的提问来源于stack exchange,提问作者Akash Sateesh
相关产品推荐
相关产品推荐

