最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Ref callback attribute is not working as expected - Stack Overflow

programmeradmin5浏览0评论

I've two examples using the ref callback attribute. The first on has a reference to the callback function. The second one has an arrow function declared as the value.

The first works as expected. But, the second one log a null on consecutive renders.

What is the reason for this?

Start typing inside the input box

Example 1(this works fine)

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=".1.0/react.min.js"></script>
<script src=".1.0/react-dom.min.js"></script>
<div id="app"></div>

I've two examples using the ref callback attribute. The first on has a reference to the callback function. The second one has an arrow function declared as the value.

The first works as expected. But, the second one log a null on consecutive renders.

What is the reason for this?

Start typing inside the input box

Example 1(this works fine)

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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Example 2 (this is not working)

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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Share Improve this question edited May 23, 2018 at 12:18 Pranesh Ravi asked Oct 30, 2016 at 14:04 Pranesh RaviPranesh Ravi 19.1k10 gold badges50 silver badges70 bronze badges 3
  • <input type="text" value={this.state.value} ref="whatever" onChange={() => this.setState({value: this.refs.whatever.value})} /> – devellopah Commented Oct 30, 2016 at 14:38
  • I know ref string will work. I need to know about ref callback attribute. React will deprecate string ref in future releases. – Pranesh Ravi Commented Oct 30, 2016 at 14:39
  • <input type="text" value={this.state.value} ref={ref => this.whatever = ref} onChange={() => this.setState({value: this.whatever.input.value})} /> – devellopah Commented Oct 30, 2016 at 14:41
Add a ment  | 

2 Answers 2

Reset to default 3

Adding to Fabian Schultz

This happens because in the first case, you're passing a reference of the function to the ref. During the initial render, the referenced function will be instantiate (a instance is created) and the element will be passed to that function. For the following renders(re-renders), this instance remains the same. So, React won't call this function as it is already being called.

But, in the second case, a arrow function is passed in as a value. So, for every re-renders the function will be passed again as the value. This results in two instances of arrow functions. One, from the previous render and the second from the recent render. Due to this, React nullifies the previous instance of the function. So, it returns null for the previous instance of the function and returns the element to the recent instance of the function.

Point to take: Always use function reference for ref

Hope this helps!

This has been discussed briefly on React's Github issues. I'll try to explain this, but it's kind of hard to put in words.

Since you're not calling a "smart" ponent method in your second example, the console.log(el) happens every time the ponent is re-rendered, which means it also calls when the specific node (in this case your input) is removed and rendered again, regardless if the el actually changed. When it is being removed by React it returns null because the element doesn't exist anymore, even if it's just for a fraction of a second. Seems like this is done for the sake of pletion.

Here's a tweet by Dan Abramov explaining this a little.

发布评论

评论列表(0)

  1. 暂无评论