为什么ref ='string'是“legacy”?

在React文档中他们说:

React还支持使用string(而不是callback函数 )作为任何组件的引用,尽pipe这种方法在这一点上大部分是遗留的

https://facebook.github.io/react/docs/more-about-refs.html

以下面的例子:

class Foo extends Component { render() { return <input onClick={() => this.action()} ref={input => this._input = input} />; } action() { console.log(this._input.value); } } 

为什么我应该喜欢这个,而不是:

 class Foo extends Component { render() { return <input onClick={() => this.action()} ref='input' />; } action() { console.log(this.refs.input.value); } } 

第二个例子看起来更干净简单。
是否有风险,string方法将被弃用?

注意 :我正在寻找文件中对“声明”的“官方”答复,我并不是在询问个人的喜好等等。

虽然也许更简单,但旧的参考API可能在某些边缘情况下变得困难,例如在callback中使用。 所有types的静态分析也是一个string的痛苦。 基于callback的API可以完成stringAPI所能做的所有事情,而且只需添加一些冗长的内容即可。

 class Repeat extends React.Component { render() { return <ul> { [...Array(+this.props.times)].map((_, i) => { return <li key={i}> { this.props.template(i) } </li> }) } </ul> } } class Hello extends React.Component { constructor() { super(); this.refDict = {}; } render() { return <Repeat times="3" template={i => <span ref= {el => this.refDict[i] = el}> Hello {i} </span>} /> {/* ^^^ Try doing this with the string API */} } } 

进一步的讨论和基于string的api的可能的问题的更全面的列表可以从#1373的问题中find,其中引入了基于callback的API。 我将在这里列出问题描述中的一个列表:

ref API被打破了几个方面。

  • 您必须将this.refs ['myname']作为string引用,以便与Closure Compiler高级模式兼容。

  • 它不允许单个实例的多个所有者的概念。

  • 神奇的dynamicstring可能会破坏虚拟机的优化。

  • 它需要始终保持一致,因为它是同步解决的。 这意味着渲染的asynchronous批处理会引入潜在的错误。

  • 我们现在有一个钩子来获取兄弟参考,这样你可以有一个组件引用它的兄弟作为上下文引用。 这只能工作一个级别。 这打破了封装中的封装之一的能力。

  • 它不能被静态input。 你必须在像TypeScript这样的语言中使用它。

  • 没有办法将ref附加到由小孩调用的callback中正确的“所有者”。 这个ref将被附加在发出callback的地方,而不是当前所有者。


文档调用旧的stringAPI “传统” ,使其更清楚的是基于callback的API是首选的方法,正如在此提交和在这个PR中讨论的那些实际上把这些语句放在第一个文档地点。 另外请注意,一些评论意味着基于string的ref api在某些时候可能会被弃用

最初张贴由danabramov在https://news.ycombinator.com/edit?id=12093234

  1. string参考不可组合。 如果一个包装组件已经有一个现有的stringref,那么它就不能“窥探”一个孩子的引用。 另一方面,callback引用没有一个所有者,所以你可以随时编写它们。
  2. string引用不能像Flow一样使用静态分析。 stream无法猜测框架做的魔术,使stringref“出现” this.refs ,以及它的types(这可能是不同的)。 callback引用对静态分析更友好。
  3. stringref的所有者由当前正在执行的组件确定。 这意味着使用通用的“render callback”模式(例如<DataTable renderRow={this.renderRow} /> ),错误的组件将拥有ref(它将以DataTable而不是定义renderRow的组件)。
  4. String refs强制React跟踪当前正在执行的组件。 这是有问题的,因为它使得react模块有状态,因此当react模块被复制到束中时引起奇怪的错误。