为啥我无法从 ReactDOM.render() 回调中获取对我的组件的引用?

Posted

技术标签:

【中文标题】为啥我无法从 ReactDOM.render() 回调中获取对我的组件的引用?【英文标题】:Why can I not get a reference to my component from the ReactDOM.render() callback?为什么我无法从 ReactDOM.render() 回调中获取对我的组件的引用? 【发布时间】:2017-04-22 07:58:51 【问题描述】:

我有以下代码:

const priceCalculator = ReactDOM.render(<PriceCalculator />, reactHolder);

我需要稍后在我的代码中使用priceCalculator,但 ESLint 抱怨我不应该使用ReactDOM.render() 的返回值。那时我发现您可以将pass a 3rd argument 转为ReactDOM.render(),这是一个回调。太好了,我想...

ReactDOM.render(<PriceCalculator />, reactHolder, function(priceCalculator) 
    // do something with priceCalculator
);

但是priceCalculator 是未定义的。在调试器中,我暂停了异常,发现this 在我在这个函数中时被设置为我的 React 组件。所以我重写它...

ReactDOM.render(<PriceCalculator />, reactHolder, function() 
    const priceCalculator = this;
    // do something with priceCalculator
);

它仍然未定义。怎么回事?

我正在使用 Webpack 编译 es6 React 代码(使用 babel)。

【问题讨论】:

ReactDOM.render 将给定的组件渲染到给定的 DOM 元素中。我相信回调是在渲染完成时调用的。也许你想要的只是做const priceCalculator = &lt;PriceCalculator /&gt; @sdgluck 这就是我首先做的,它工作正常。但是不鼓励这种方式,因为最终 ReactDOM.render 可能不会返回任何东西github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/… 回调似乎在小提琴中正常工作:jsfiddle.net/69z2wepo/64439 @sdgluck 我看错了你的答案......没有注意到你没有使用渲染。我需要引用我的组件的特定实例,因为我将侦听器附加到现有(非反应)DOM 节点。这些监听器需要调用我的组件实例的方法。 示例:jsfiddle.net/2zbxats7/1 【参考方案1】:

在您链接的ESLint docs page 中,它说要使用callback ref:

ReactDOM.render() 当前返回对根 ReactComponent 实例的引用。然而,使用这个返回值是遗留的,应该避免,因为未来版本的 React 在某些情况下可能会异步渲染组件。 如果您需要对根 ReactComponent 实例的引用,首选的解决方案是将 callback ref 附加到根元素。

来源:React Top-Level API documentation

因此,您可以通过 prop 将回调传递给根组件,并通过根节点的 ref prop 从其 render 方法中引用组件的根节点来调用它。

例如(working fiddle):

class Hello extends React.Component 
  render () 
    return (
      <div ref=(node) => this.props.cb(node)>
        Hello this.state.name
      </div>
    )
  


let node

ReactDOM.render(<Hello cb=(n) => node = n />, ...);

console.log(node)

注意:这种方法很幼稚,因为ReactDOM.render 可能并不总是同步渲染,在这种情况下console.log 语句将打印"undefined"。 (参见上面的引用:“React 的未来版本在某些情况下可能会异步渲染组件”。)

【讨论】:

我调整了你的小提琴,使其更像我想要达到的目标jsfiddle.net/n92sm5f3/1 它确实有效(太棒了!)但我仍然不明白为什么其他方式不能。我链接到的文档页面也说ReactDOM.render(&lt;App /&gt;, document.body, doSomethingWithInst); 应该可以工作。 是的,这令人困惑。也许该功能不再可用并且文档已过时 - 您是否使用较旧的 React v. 进行了测试?无论哪种方式,这是推荐的方法。 :-)

以上是关于为啥我无法从 ReactDOM.render() 回调中获取对我的组件的引用?的主要内容,如果未能解决你的问题,请参考以下文章

ReactDOM.render:React 从 16.4.2 升级到 16.5.2 后,无法在未安装的组件上找到节点

ReactDOM.render 与 React 组件渲染区别

ReactDOM.render和ReactDOM.createPortal

第十五篇:ReactDOM.render 是如何串联渲染链路的?(下)

第十五篇:ReactDOM.render 是如何串联渲染链路的?(下)

TypeScript 和 ReactDOM.render 方法不接受组件