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); };
In the React18 version, why does clicking the handleClick
method cause two renderings, while clicking the handleClick2
method only causes one rendering?
I want the output of both methods to be the same. Can anyone tell me why they are different?
I will explain how these call sequences differ and how the observed behavior is possible.
I can’t tell you exactly how React updates status in batches internally, I just assume that React has complex optimizations that are irrelevant to the developer using React and require a deep understanding of React internals and maybe even changing from one version to another. (Please feel free to correct me.)
the difference
Promise.resolve()
Arranges a new microtask, which is actually equivalent towindow.queueMicrotask()
.setState
Function (possibly) will also schedule a new microtask, Therefore their callbacks (Promise
andsetState
) are called in the same execution phase.The difference between these two variants is
handleClickA
, thesetState2
hook is called between the twoupdater
functions, whilehandleClickB
, the twoupdater
functions will be called directly in sequence.Sample code
I rewrote your code slightly to better illustrate the calling sequence:
Call sequence description
Here I explain the calling sequence.
(FIFO >):
handleClickA
:handleClickB
:Personal interpretation
I assume React attempts to batch all
updater
functions currently queued.i.e. whenever only the updater function is called, try batching them together and only update the final state once.
However, if a new
I can only guess why this is donesetState
function is called, React may complete the current update loop and start a new render before calling the nextupdater periodic function. 代码>
Because the new- setState
If new - setState
React people are still figuring out the best optimization strategies and their trade-offs. -
(...or this is a bug.) -
might somehow break the batch, or
calls are made recursively, the next render will be delayed too much, or