setState什么时候是同步 什么时候是异步
看下面的代码:
// 异步场景1
state={
count:0
}
componntDidMount(){
this.setState({
count:this.state.count + 1
},()=>{
consoloe.log(this.state.count) // 1
})
this.setState({
count:this.state.count + 1
},()=>{
console.log(this.state.count) // 1
})
}
// 异步场景2
state= {
count: 0
}
componntDidMount(){
this.setState(perState=>{
count:perState.count +1
},()=>{
console.log(this.state.count) // 1
})
this.setState(perState=>{
count:perState.count +1
},()=>{
console.log(this.state.count) // 2
})
通常认为为了优化,通过异步的处理方式,累计更新后,批量合并处理,减少渲染次数,优化性能
那同步呢:
// 同步场景
state= {
count: 0
}
componntDidMount(){
this.setState({count:this.state.count +1})
console.log(this.state.count) // 0
setTimeout(()=>{ // 同步
this.setState({
count:this.state.count+1
});
console.log(this.state.count) // 1
},300)
}
为什么setState是异步的:
react官方回答是:保持内部的一致性,如果改成同步更新的模式,setState是同步更新的,但是props不是
为后续的架构升级启用并发更新,为了完成异步渲染,react会更具他们的数据来源,分配不同的优先级,这些数据来源有事件后调拒币的动画效果,在更具优先级,并发处理,提升渲染性能。
其实react并非异步:
setState其实他并不是真正的异步,其实看上去是异步,他是通过队列延迟执行来模拟实现的,
通过isbatchUpdate来判断,如果为true则是先存入set队列执行异步操作,false为同步更新。
在onClick,onfucos事件中,由于合成事件封装了一层,所以可以将isbatchUpdate的状态更新为true,
在react生命周期函数中,同样可以将isbatchUpdate更新为true。在react自己的生命周期事件和合成事件中
可以拿到isBatchingUpdate的控制权,将状态放进队列中,控制执行节奏,但是在外部的原生事件中(addEventListener,setTimeOut,setInterval)并没有外层
的封装拦截,无法更新isBatchingUpdate的状态为true。这就造成isBatchingUpdate的状态为false,切一直执行,同步更新
state= {
count: 0
}
componntDidMount(){
this.setState({count:this.state.count +1})
console.log(this.state.count) // 0
this.setState({count:this.state.count +1})
console.log(this.state.count) // 0
setTimeout(()=>{ // 同步
this.setState({
count:this.state.count+1
});
console.log(this.state.count) // 2
this.setState({
count:this.state.count+1
});
console.log(this.state.count) // 3
},300)
}