setState有时异步,有时同步,有时合并,有时不合并。
- 正常调用时是异步的,在setTimeout和自定义Dom事件里是同步的。
- 传入对象时会被合并,传入函数时不合并。
1. 异步(普通使用)
this.setState({
count: this.state.count + 1
}, () => {
console.log('count by callback', this.state.count) // 回调函数中可以拿到最新的 state
})
console.log('count', this.state.count) // 异步的,拿不到最新值
2. 同步(setTimeout、Dom事件)
在setTimeout里是同步的
// setTimeout 中 setState 是同步的
setTimeout(() => {
this.setState({
count: this.state.count + 1
})
console.log('count in setTimeout', this.state.count)
}, 0)
在自己定义的dom事件里是同步的
componentDidMount() {
// 自己定义的 DOM 事件,setState 是同步的
document.body.addEventListener('click', this.bodyClickHandler)
}
3. 合并(对象形式)
传入对象,会被合并(类似 Object.assign )。执行结果只一次 +1
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
4. 不合并(函数形式)
传入函数,不会被合并。执行结果是 +3
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
}
})