react的setState机制
什么场景下,setState会同步更新
同步更新
如果setState在以下场景里调用多次
addEventListener事件回调里
js
window.addEventListener('click',() => {
this.setState({
a: 1
})
this.setState({
b: 2
})
})setTimeout、setInterval、promise回调里
js
setTimeout(() => {
this.setState({
a: 1
})
this.setState({
b: 2
})
},10)那么回调里的多个setState会同步执行。且执行多次。以上面例子为例,setState会触发两次渲染
异步更新
如果setState写在react元素绑定的事件回调里
则setState会异步执行,setState只触发一次渲染
注意: 从React18以及以上版本开始,setState都是异步更新且合并state
什么场景下,setState会合并state(批量更新)
合并场景
如果setState满足同步执行,则不会合并state
js
this.state = {
count: 0,
}
setTimeout(() => {
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
}, 1000)以上代码执行后。count显示为3。 因为此时setState代码同步执行,所以更新顺序是第一个setState先把count变成1,然后渲染一次。第二个setState先把count变成2,然后再重新渲染一次。第三个setState把count变成3,触发最后一次渲染。
总结下就是会触发3次渲染,界面依次更新成1、2、3。只是界面渲染比较快,看起来是从0直接变成3
不合并场景
如果setState满足异步执行,则会合并state
js
this.state = {
count: 0,
}
// 事件回调里
const handleClick = () => {
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
}以上代码执行后。count显示为1。 这是因为事件里setState传入的对象参数,会先存到队列里,比如上面例子中,队列里状态为[{count:1},{count:1},{count:1}],然后触发点击事件时,三个对象会进行合并,变成{count:1},然后再进行渲染。 从上面步骤可以看出与同步执行的setState的区别,异步setState只触发一次渲染,且是直接从0变成1
但是,需要注意! 如果setState传入的是函数,此时不会合并
js
this.state = {
count: 0,
}
// 事件回调里
const handleClick = () => {
this.setState((prevState, props) => {
return {
count: prevState.count + 1
}
})
this.setState((prevState, props) => {
return {
count: prevState.count + 1
}
})
this.setState((prevState, props) => {
return {
count: prevState.count + 1
}
})
}以上代码执行后。count显示为3