useEffect(() => { console.log("render"); }); const handleClick = () => { setC1((c) => c + 1); Promise.resolve().then(() => { setC1((c) => c + 1); }); }; const handleClick2 = () => { Promise.resolve().then(() => { setC1((c) => c + 1); }); setC1((c) => c + 1); };
在React18版本中,为什么点击handleClick
方法会出现两次渲染,而点击handleClick2
方法只会出现一次渲染?
我希望这两种方法的输出是相同的。谁能告诉我为什么它们不同?
我将解释这些调用顺序有何不同,以及观察到的行为如何可能。
我无法确切地告诉你 React 内部是如何批量更新状态的, 我只是假设 React 进行了复杂的优化,这与使用 React 的开发人员无关,并且需要深入了解 React 内部,甚至可能从一个版本更改为另一个版本。 (请随时纠正我。)
区别
Promise.resolve()
安排一个新的微任务,实际上相当于window.queueMicrotask()
。setState
函数(可能)还会安排一个新的微任务, 因此它们的回调(Promise
和setState
)都是在同一执行阶段调用的。这两个变体的区别在于
handleClickA
中,在两个updater
函数之间调用setState2
挂钩,而handleClickB
中,两个updater
函数都会直接依次调用。示例代码
我稍微重写了您的代码,以更好地说明调用顺序:
呼叫顺序说明
这里我说明了调用顺序。
(FIFO >):
handleClickA
:handleClickB
:个人解读
我假设 React 尝试对当前排队的所有
updater
函数进行批处理。即只要仅调用更新器函数,请尝试将它们批处理在一起并仅更新一次最终状态。
但是,如果调用了新的
setState
函数,React 可能会完成当前更新循环,并在调用下一个updater 之前启动新的渲染周期代码> 函数。
我只能猜测为什么要这样做
setState
可能会以某种方式破坏批处理,或者setState
调用,下一次渲染将会延迟太多,或者