异步连续两次执行useState
,两次设置的值都相同。先打印 cccccccccccccccc
,后打印pppppppppppp
异步只执行一次,结果却是相反。
我的理解useEffect
是监听a
的变化后才执行,而且useState
是异步的。理论来说不管是执行几次useState
肯定都是先打印pppppppppppp
再打印cccccccccccccccc
吧?
但结果为什么会这样呢?完全理解不了,请大佬们帮忙解释下
难道是因为在异步请求中多次执行useState
在赋值成功前会阻塞后续代码执行?是一种同步的场景?
react react-dom
版本 16.13.1
首先明确一个点,在 react18 之前,异步任务中 setState 不会被 batch(合并执行),也就是说如下两种场景存在更新流程的差异
异步任务中 setState
在异步更新的流程中,由于没有 batch,所以组件会更新两次,下面浅析一下这两次更新操作在 react 中是如何调度的
可以看到,只有在多次 setA 操作下,前面的 setA 才会被同步执行。其实说白了,setA 是否同步更新,取决于后面是否还有 setA
所以如果这里只有一次 setA 操作,那么也是走的异步更新
这也就是为什么在你的 demo 中,两次 setA,看到的是先 ccccccc,后 ppppppp, 原因就是第二个 setA 触发了第一个 setA 更新任务的同步执行,而第二个 setA 的更新任务则是正常被调度器异步调度执行的。如果你是这样写
那么结果应该是
同步任务中的 setState
同步的过程会进行 batch,因此只会有一次更新
最后
具体可以去看看 react-reconciler 部分 scheduleUpdateOnFiber 的实现。react18版本后,异步任务中的更新默认也是 batch 的,所以默认情况下不会出现你 demo 中的问题了