为什么ref =' string'是"遗产"?

时间:2016-05-26 18:52:47

标签: reactjs

在React文档中,他们说:

  

React还支持使用字符串(而不是回调)作为任何组件的ref prop,尽管此方法主要是遗留

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);
  }
}

第二个例子似乎更干净,更容易 是否存在不推荐使用字符串方法的风险?


NB :我正在寻找&#34;官方&#34;回答文档中的陈述,我不询问个人偏好等。

2 个答案:

答案 0 :(得分:42)

虽然可能更简单,但旧的refs API在某些边缘情况下可能会变得困难,就像在回调中使用时一样。所有类型的静态分析也都是字符串的痛苦。基于回调的API可以完成字符串API可以执行和更多的所有操作,只需添加一点点详细信息。

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          */}
  }
}

可以在issue #1373中找到有关基于字符串的api可能出现的问题的进一步讨论和更全面的列表,其中引入了基于回调的api。我将在此处列出问题说明中的列表:

  

ref API被破坏了几个方面。

     
      
  • 您必须将this.refs [&#39; myname&#39;]视为与Closure Compiler Advanced Mode兼容的字符串。

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

  •   
  • 神奇的动态字符串可能会破坏虚拟机中的优化。

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

  •   
  • 我们目前有一个钩子来获取兄弟参考,以便您可以让一个组件将它作为上下文参考引用它的兄弟。这仅适用于一个级别。这打破了将其中一个包装在封装中的能力。

  •   
  • 无法静态输入。您必须使用TypeScript等语言进行强制转换。

  •   
  • 无法将裁判附加到正确的&#34;所有者&#34;在由孩子调用的回调中。 <Child renderer={index => <div ref="test">{index}</div>} /> - 此引用将附加在发出回调的位置,而不是当前所有者。

  •   

文档调用旧的字符串API &#34; legacy&#34; ,以更清楚地表明基于回调的API是首选方法,如this commit中所讨论的那样在this PR中,这些实际上是将这些语句放在文档中的。另请注意,一些注释暗示基于字符串的refs api可能在某个时候已弃用

答案 1 :(得分:16)

最初由danabramov发表于https://news.ycombinator.com/edit?id=12093234

  
      
  1. 字符串引用不可组合。如果已经有一个现有的字符串引用,则包装组件不能“窥探”对子进程的引用。另一方面,回调引用没有一个所有者,所以你总是可以组成它们。
  2.   
  3. String refs不适用于像Flow这样的静态分析。 Flow无法猜测框架在this.refs上使字符串ref“出现”以及其类型(可能不同)所具有的魔力。回调引用对静态分析更友好。
  4.   
  5. 字符串ref的所有者由当前正在执行的组件确定。这意味着使用常见的“渲染回调”模式(例如<DataTable renderRow={this.renderRow} />),错误的组件将拥有参考(它将最终在DataTable而非您定义renderRow的组件)。
  6.   
  7. String refs force React跟踪当前正在执行的组件。这是有问题的,因为它使react模块有状态,因此当捆绑中react模块重复时会导致奇怪的错误。
  8.