Ref 回调属性未按预期工作

IT技术 javascript reactjs
2021-05-19 22:13:44

我有两个使用ref callback attribute. 第一个 on 引用了回调函数。第二个有一个箭头函数声明为值。

第一个按预期工作。但是,第二个记录null连续渲染。

这是什么原因?

开始在输入框内输入

示例 1(这工作正常)

class App extends React.Component{
  constructor(props){
    super(props)
    this.refCallback = this.refCallback.bind(this)
    this.state = {}
  }
  
  refCallback(el){
    console.log(el)
  }
  
  render(){
    return <input type="text"
      value={this.state.value}
      ref={this.refCallback}
      onChange={(e) => this.setState({value: e.target.value})}
      />
  }
}

ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

示例 2(这不起作用)

class App extends React.Component{
  constructor(props){
    super(props)
    this.state = {}
  }

  render(){
    return <input type="text"
      value={this.state.value}
      ref={(el) => console.log(el)}
      onChange={(e) => this.setState({value: e.target.value})}
      />
  }
}

ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

2个回答

添加到Fabian Schultz

发生这种情况是因为在第一种情况下,您将函数的引用传递给ref. 在初始渲染期间,引用的函数将是instantiate(创建一个实例)并将element传递给该函数。对于以下渲染(重新渲染),此实例保持不变。所以,React不会调用这个函数,因为它已经被调用了。

但是,在第二种情况下,箭头函数作为值传入。因此,对于每次重新渲染,该函数将作为值再次传递。这导致箭头函数的两个实例。一个,来自之前的渲染,第二个来自最近的渲染。因此,Reactnullifies函数的前一个实例。因此,它返回null函数的前一个实例,并返回函数element的最近实例。

要点:始终使用函数引用 ref

希望这可以帮助!

这已在 React 的 Github 问题 上简要讨论过我会试着解释这一点,但这有点难以用语言表达。

由于您没有在第二个示例中调用“智能”组件方法,因此console.log(el)每次重新渲染组件时都会发生这种情况,这意味着它也会在删除并再次渲染特定节点(在本例中为您的输入)时调用,不管是否el真的改变了。当它被 React 删除时,它会返回,null因为该元素不再存在,即使它只存在几分之一秒。似乎这样做是为了完成。

这是丹·阿布拉莫夫 (Dan Abramov)的一条推文,对此进行了一些解释。