React version: 18.0.0
Steps To Reproduce
Normal example
The following example is normal. The value of count is incremented by 1 when click the button.
The update of Code Snippet A、Code Snippet B and Code Snippet C will be all batch. Because by the time the code executes to Code Snippet A and Code Snippet C, Code Snippet B has already been added to the microtask queue. The flushSyncCallbacks are executed in scheduleMicrotask callback function, therefore, Code Snippet B is executed first and then flushSyncCallbacks is executed.
import { useEffect, useState, useRef } from "react";
export default function App() {
const [count, setCount] = useState(0);
const countRef = useRef(-1);
const handleClickButton = () => {
// No.B
Promise.resolve().then(() => {
setCount(countRef.current + 1);
});
// No.A
setCount(countRef.current + 1);
// No.C
setCount(countRef.current + 1);
// Code Snippet A、Code Snippet B and Code Snippet C are all batch processed
};
useEffect(() => {
countRef.current = count;
}, [count]);
return (
<div>
<p>count is: {count}</p>
{/* count will be incremented by 1 when click the button */}
<button onClick={handleClickButton}>增加</button>
</div>
);
}
link to code example: https://codesandbox.io/s/batch-update-in-native-xpwz33-forked-c4pii4?file=/src/App.js:0-581
Abnormal examples
The following example is abnormal. The value of count is incremented by 2 when click the button.
The update of Code Snippet A and Code Snippet C will be batch, but the update ofCode Snippet B won't be batch.
When the code executes to Code Snippet C, Code Snippet B has not been batch, although Code Snippet B has been added to the microtask queue.
I think all updates added to the microtask queue should be batched when the code executes to the last update on the synchronous execution context.
import { useEffect, useState, useRef } from "react";
export default function App() {
const [count, setCount] = useState(0);
const countRef = useRef(-1);
const handleClickButton = () => {
// Code Snippet A
setCount(countRef.current + 1);
Promise.resolve().then(() => {
// Code Snippet B
setCount(countRef.current + 1);
});
// Code Snippet C
setCount(countRef.current + 1);
// Code Snippet A and Code Snippet C will be batch, but Code Snippet B won't be batch
};
useEffect(() => {
countRef.current = count;
}, [count]);
return (
<div>
{/* count will be incremented by 2 when click the button */}
<p>count is: {count}</p>
<button onClick={handleClickButton}>增加</button>
</div>
);
}
Link to code example: https://codesandbox.io/s/batch-update-in-native-xpwz33-xpwz33?file=/src/App.js:0-581
The current behavior
When a setState is executed first in the synchronous execution context, all setState in the microtask queue will not be batched, even if the synchronous execution context still has setState after these microtasks.
The expected behavior
All updates added to the microtask queue should be batched when the code executes to the last update on the synchronous execution stack.
React version: 18.0.0
Steps To Reproduce
Normal example
The following example is normal. The value of
countis incremented by1when click the button.The update of
Code Snippet A、Code Snippet BandCode Snippet Cwill be all batch. Because by the time the code executes toCode Snippet AandCode Snippet C,Code Snippet Bhas already been added to the microtask queue. TheflushSyncCallbacksare executed inscheduleMicrotaskcallback function, therefore,Code Snippet Bis executed first and thenflushSyncCallbacksis executed.link to code example: https://codesandbox.io/s/batch-update-in-native-xpwz33-forked-c4pii4?file=/src/App.js:0-581
Abnormal examples
The following example is abnormal. The value of
countis incremented by2when click the button.The update of
Code Snippet AandCode Snippet Cwill be batch, but the update ofCode Snippet Bwon't be batch.When the code executes to
Code Snippet C,Code Snippet Bhas not been batch, althoughCode Snippet Bhas been added to the microtask queue.I think all updates added to the microtask queue should be batched when the code executes to the last update on the synchronous execution context.
Link to code example: https://codesandbox.io/s/batch-update-in-native-xpwz33-xpwz33?file=/src/App.js:0-581
The current behavior
When a
setStateis executed first in the synchronous execution context, allsetStatein the microtask queue will not be batched, even if the synchronous execution context still hassetStateafter these microtasks.The expected behavior
All updates added to the microtask queue should be batched when the code executes to the last update on the synchronous execution stack.