谈谈理解,不保证其准确性
setState 只在合成事件和钩子函数中是异步的,在原生事件和任务队列里都是同步的
一:什么是react合成事件和钩子函数
react自己封装的事件系统就是合成事件,用来代替原生事件,如jsx里的onClick,onChange等事件都是合成事件;
钩子函数就是didMonut,stateFromProps等
二:什么是原生事件和任务队列
原生事件指的是非react合成事件,如 document.querySelector().onclick 这种绑定事件的形式
任务队列就是setTimeout,promise then等
三:setState 的批量更新概念
只有异步才有批量更新。当更新的key是同一个值,setstate批量更新策略会进行覆盖,只取最后一次执行;当更新的key是不同值,那么会进行合并并更新
四:setState异步概念
setState的异步并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在dom更新之前,导致在合成事件和钩子函数中不能拿到更新后的值,形式了所谓的“异步”,当然可以通过setState(partialState, callback) 第二个参数 中的callback拿到更新后的结果。
React-dom源码版本16.4.1中:有个try{}finally{},合成事件和钩子函数代码块中的执行都是在try里,执行完毕才走到finally里performSyncWork方法,该方法执行完毕才会重新渲染dom
五:实例代码
constructor(props) {
super(props);
this.state = {val:0};
}
componentDidMount() {
this.setState({val: this.state.val+1})
console.log(this.state.val,1)
this.setState({val: this.state.val+1})
console.log(this.state.val,2)
new Promise((resolve) => {
resolve()
}).then(_ => {
this.setState({val: this.state.val+1})
console.log(this.state.val,3)
this.setState({val: this.state.val+1})
console.log(this.state.val,4)
})
}
打印出来的val分别是0,0,2,3
前两次打印是钩子函数异步批量更新,只执行后一次setState,此时console并不能获取到最新的,会显示0;任务队列promise里setState是同步的,更新完dom以后执行console,此时可以获取到最新的val值