大家都知道,react中的state不能直接修改,只能通过setState()来修改。
setState()的更新可能是异步的
异步的情况:
- 出于性能考虑,react会把多个setState()调用合并成一个。 代码如下: 观察控制台的打印与页面上counter的值,发现不同步。
changeValue = v => {
this.setState(
{
counter: this.state.counter + v
})
console.log('counter不同步====', this.state.counter);//不同步,如果不用setTimout 和setState回调的话
}
setCounter = () => {
//setState在setTimout和原生事件中是同步的
this.changeValue(1);
// console.log('this.state.counter====', this.state.counter);
}
render() {
const { counter } = this.state
return (
<div>
<h3>setStatePage</h3>
<button onClick={this.setCounter}>{counter}</button>
<button id="test">原生事件:{counter}</button>
</div>
)
}

setCounter = () => {
this.changeValue(1);
this.changeValue(2); //只会调用这个,上面的this.changeValue(1)不会被调用
// console.log('this.state.counter====', this.state.counter);
}
同步的情况
- 在回调中获取状态值
changeValue = v => {
this.setState(
{
counter: this.state.counter + v
},
() => {
console.log('counter同步====', this.state.counter);
}
)
//console.log('counter不同步====', this.state.counter);//不同步,如果不用setTimout 和setState回调的话
}
- 在setTimeout中调用changeValue
setCounter = () => {
//setState在setTimout中是同步的
setTimeout(() => {
this.changeValue(1);
this.changeValue(2); //两个changeValue都运行所以一共是加3 ,先加1,再加2
}, 1000)
}
- 在原生事件中是同步的
componentDidMount() {
document.getElementById("test").addEventListener('click', this.setCounter)
}
render() {
const { counter } = this.state
return (
<div>
<button id="test">原生事件:{counter}</button>
</div>
)
}
总结:setState只在合成事件和生命周期函数中是异步的,在原生事件和setTimeout中都是同步的。