【React】react中ref使用的问题?

官网资料:react中使用ref的注意点

If the ref callback is defined as an inline function, it will get called twice during updates, first with null and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one. You can avoid this by defining the ref callback as a bound method on the class, but note that it shouldn’t matter in most cases.

大概意思就是,如果ref的回调函数是行内函数,那么状态更新时,这个回调函数将执行两次,一次返回null,第二次返回真正的dom节点,如果想避免这个问题,就将ref的回调指向class上的一个方法。

按照官网教程的意思,我写了一段测试代码,ref回调函数为行内函数:

class App extends React.Component {

constructor(){

super();

this.state={

text:""

}

}

componentDidMount(){

// console.log(this);

}

changeInput(event){

this.setState({

text:event.target.value

});

}

render() {

return (

<input type="text"

ref={(textInput)=>{console.log('111',textInput);this.textInput=textInput;}}

onChange={this.changeInput.bind(this)}

value={this.state.text}

/>

);

}

}

运行结果为:

【React】react中ref使用的问题?

每次状态更新,确实执行了两次。现在将ref的回调指向class上的一个方法。代码如下:

class App extends React.Component {

constructor(){

super();

this.state={

text:""

}

}

componentDidMount(){

// console.log(this);

}

getInputDom(textInput){

console.log('111',textInput);

this.textInput=textInput;

}

changeInput(event){

this.setState({

text:event.target.value

});

}

render() {

return (

<input type="text"

ref={this.getInputDom.bind(this)}

onChange={this.changeInput.bind(this)}

value={this.state.text}

/>

);

}

}

打印结果为:

【React】react中ref使用的问题?

奇怪的是,状态更新时,还是执行了两次,和上面的执行结果一模一样。

那么问题来了,为什么ref的回调函数会执行两次呢?为什么ref的回调函数是行内函数或是指向class上的一个方法时,运行结果一模一样呢?这和官网解释的不一样呀。

回答

关键在于bind(this)。

#9328

What do you mean by “fixing”? The behavior is intentional. If you pass an arrow function, referentially it is different every time. React has no way to know if it’s the same function in the code or not, so it has to “clean up” the old ref and “set up” the new ref just in case they turn out to be truly different functions. And cleaning up is necessary to avoid stale references (and memory leaks).

上面是维护者(?)的回复,他里面说了一句很关键的,如果你传了一个匿名箭头函数,那么对于react来说,它每次都是不一样的。所以会"clean up"掉老的ref再"set up"。

而bind(this)起的作用是一样的,每次render都会重新调用一次bind,bind会返回一个新的函数,所以这里和匿名箭头函数是一样的。

解决办法是在constructor中调用bind。

或者用下面这种方式定义函数

getInputDom = ref => {}

直接 ref => this.textInput = ref 就好了,为什么还要在 ref 函数中写逻辑呢?要深究为啥执行两次的话要去看 react.jsref 实现了。

用这种方式可以避免 null:
<input ref='inputRef' />
然后,this.inputRef = this.refs.inputRef

以上是 【React】react中ref使用的问题? 的全部内容, 来源链接: utcz.com/a/72885.html

回到顶部