Pranesh Ravi Pranesh Ravi - 1 month ago 5
Javascript Question

Ref callback attribute is not working as expected

I've two examples using the

ref callback attribute
. The first on has a reference to the callback function. The second one has an anonymous 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?

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.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>





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.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>




Answer

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" component method in your second example, the console.log(el) happens every time the component 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 completion.

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

Comments