React中setState是同步还是异步的?

React setState是同步还是异步的

image.png

  • 输出结果为: 0,0,2,3

react内部为了优化setState()的批处理,会对setState()进行合并,并且对相同属性的设置只保留最后一次的设置,类似于函数Object.assign()。

在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到一个updateQueue中延时更新,而 isBatchingUpdates 默认是 false,表示 setState 会同步更新 this.state;但是,有一个函数 batchedUpdates,该函数会把 isBatchingUpdates 修改为 true,而当 React 在调用事件处理函数之前就会先调用这个 batchedUpdatesisBatchingUpdates修改为true,这样由 React 控制的事件处理过程 setState 不会同步更新 this.state,而是异步的。

结合上面分析的,钩子函数中的 setState 无法立马拿到更新后的值,所以前两次都是输出0,当执行到 setTimeout 里的时候,前面两个state的值已经被更新,由于 setState 批量更新的策略, this.state.val 只对最后一次的生效,为1,而在 setTimmout 中 setState 是可以同步拿到更新结果,所以 setTimeout 中的两次输出2,3,最终结果就为 0, 0, 2, 3 。

setState()可以接收一个对象外,还可以接收一个函数:

区别:

传递对象: 批处理,对相同变量进行的多次处理会合并为一个,并以最后一次的处理结果为准。

传递函数: 链式调用,React 会把我们更新 state 的函数加入到一个队列里面,然后,按照函数的顺序依次调用,不会合并为一次。同时,为每个函数传入 state 的前一个状态,这样,就能更合理的来更新我们的 state 了,该函数有两个参数prevState和props。

总结:

异步的情况:

由React控制的事件处理函数,以及生命周期函数调用setState时表现为异步 。大部分开发中用到的都是React封装的事件,比如onChange、onClick、onTouchMove等(合成事件中)以及钩子函数中,这些事件处理函数中的setState都是异步处理的。

同步的情况:

React控制之外的事件中调用setState是同步更新的。比如原生js绑定的事件,setTimeout/setInterval,ajax,promise.then内等 React 无法掌控的 APIs情况下,setState是同步更新state的。

原理:根据isBatchingUpdates来判断是否批量更新,如果当前setState命中了batchUpdate机制,就会异步执行,如果未能命中,则会同步执行。

参考地址:

猜你喜欢

转载自blog.csdn.net/qq_38082146/article/details/115069669