先来点总结性发言
setState({obj})这种形式,本质上与我们所说的异步编程概念上是不同的,只是React这个UI库内置的提升性能的一种方式,它只是把其生命周期函数和合成事件中多次操作state合并在为一次操作,避免组件多次触发更新带来的开销,一次setState,实际会go through生命周期一大圈,render生成虚拟DOM,diff比较等等,所以实际一次setState的开销也是很大的,既然连续setState,中间的一些state状态变化可能时不必的,即使变化出来,也还不是最终状态。
分析源码看原理,当调用它的一个合成事件或者可设置state的生命周期函数(such as:componentDidMount)时候,实际引入一个大的事务机制,先通过batchedUpdates方法设置batchingStrategy标识位 isBatchingUpdates = true,然后每次调用setState设置属性时,都会先把状态放到一个队列中,所有更新完成后把isBatchedUpdate置为false,事务结束时,再一次性的把队列里面的内容合并为一次state变化操作,对当前组件进行更新。
注意:
如果要获取运行到当前语句实际的state值,可以通过setState的另一个重载函数,传入一个函数,函数的参数是(pre,props) => {return {newstate}},这样运行起来就不那么迷糊了,也会react官方推荐修改state的方法,它会在批量更新过程中逐步求职并把结果传递给队列中的下一个对象进行计算。
怎么让代码运行起来立即同步更新呢?
1. setTimeout,setInterval,绕过React添加的事件处理(如:addEventListener)等里面调用setState则会逐步得到每一步的结果后再继续执行。
2. setState传入obj对象时,其实第二个参数还可以传入一个回调函数,也可以拿到最新的值,这个回调函数是在setstate执行完并页面渲染了之后再执行。