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