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

Fez*_*sta 54 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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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


注意:我正在寻找文档中声明的"官方"答案,我不是在询问个人喜好等等.

nop*_*ppa 45

虽然可能更简单,但旧的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          */}
  }
}
Run Code Online (Sandbox Code Playgroud)

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

ref API被破坏了几个方面.

  • 你必须将this.refs ['myname']称为字符串才能兼容Closure Compiler Advanced Mode.

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

  • 神奇的动态字符串可能会破坏VM中的优化.

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

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

  • 它不能静态输入.您必须使用TypeScript等语言进行转换.

  • 在由孩子调用的回调中,无法将引用附加到正确的"所有者".<Child renderer={index => <div ref="test">{index}</div>} /> - 此引用将附加在发出回调的地方,而不是当前所有者.


文档调用旧的字符串API "遗留",以更清楚地表明基于回调的API是首选方法,如本提交本PR中所述,这些是实际将这些语句放在文档中的第一个地点.另请注意,一些注释暗示基于字符串的refs api可能会在某个时候被弃用.


piz*_*r0b 17

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

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