最近复习了一些关于react
的基础,发现setState
相关的知识忘记的差不多了,所以,以这篇博客记录一下,setState使用的细节
setState的异步更新
自定义事件中为异步更新
<div>
<h2>{this.state.message}</h2>
<button onClick={e => this.changeText()}>改变文本</button>
</div>
changeText() {
this.setState({
message: "Hello React"
})
console.log(this.state.message); // Hello World, 并不能同步拿到最新值 Hello React
}
为什么setState设计为异步呢?
- setState设计为异步,可以显著的提升性能;
- 如果每次调用
setState
都进行一次更新,那么意味着render
函数会被频繁调用,界面重新渲染,这样效率是很低的;最好的办法应该是获取到多个更新,之后进行批量更新; - 如果同步更新了
state
,但是还没有执行render函数
,那么state
和props
不能保持同步;state
和props
不能保持一致性,会在开发中产生很多的问题;
- 如果每次调用
及时获取到setState异步更新后的值
setState(partialState, callback) 方法获取
changeText() {
this.setState({
message: "Hello React"
}, () => {
console.log(this.state.message); // Hello React
});
}
生命周期函数 componentDidUpdate 获取
componentDidUpdate(prevProps, provState) {
console.log(this.state.message); // Hello React
}
setState的同步更新
setTimeout 中为同步更新
changeText() {
setTimeout(() => {
this.setState({
message: "Hello React"
});
console.log(this.state.message); // Hello React
}, 0);
}
原生DOM事件中为同步更新
const btnEl = document.getElementById("btn");
btnEl.addEventListener('click', () => {
this.setState({
message: "Hello React"
});
console.log(this.state.message); // Hello React
})
setState的数据合并
- 使用
Object.assign(target, ...sources)
来完成的,每次setState
并没有直接替换state中的所有数据,而是覆盖差异项,就是setState
中的key项
setState的方法合并
- 多个
setState
连续执行,最终只会执行一个,例子中最后counter
只增加了 1
increment() {
this.setState({
counter: this.state.counter + 1
});
this.setState({
counter: this.state.counter + 1
});
this.setState({
counter: this.state.counter + 1
});
}
-
setState(callback)
取消合并,例子中最后counter
只增加了 3
increment() {
this.setState((state, props) => {
return {
counter: state.counter + 1
}
})
this.setState((state, props) => {
return {
counter: state.counter + 1
}
})
this.setState((state, props) => {
return {
counter: state.counter + 1
}
})
}
总结
- 在
组件生命周期
或React合成事件
中,setState是异步; - 在
定时器
或原生dom事件
中,setState是同步; -
setState
数据合并,实际上是Object.assign(target, ...sources)
- 通过
setState(callback)
的方式可取消setState
的多个合并
继续学习🤗~