I've found this interesting React behavior that I would like to know more about.
Usually React will batch multiple setState() calls when inside an event handler, right?
But I tested that React won't batch the calls if:
- The event handler function is an
asyncfunction with a anawaitcall. - And that
awaitcall executes before or between thesetState()calls.- If the
awaitruns after thesetState()calls, they are batched as usual.
- If the
QUESTION:
Do you know what is the reason behind this?
CodeSandbox: https://codesandbox.io/s/eventhandlerawaitso-jsdxs
This is the mockAPI call
function mockAPI() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("I come from API using an AWAIT call");
},500);
});
}
These are the handlers to test:
function handleClickNormal() {
console.clear();
console.log("Calling 1st setState()");
updateBooleanState(false);
console.log("Calling 2nd setState()");
updateBooleanState(true);
console.log("After 2nd setState()");
}
async function handleClickAwaitBefore() {
console.clear();
// AWAIT CALL RUNS BEFORE THE setState CALLS
const fromAPI = await mockAPI();
console.log(fromAPI);
console.log("Calling 1st setState()");
updateBooleanState(false);
console.log("Calling 2nd setState()");
updateBooleanState(true);
console.log("After 2nd setState()");
}
async function handleClickAwaitAfter() {
console.clear();
console.log("Calling 1st setState()");
updateBooleanState(false);
console.log("Calling 2nd setState()");
updateBooleanState(true);
console.log("After 2nd setState()");
// AWAIT CALL RUNS AFTER THE setState CALLS
const fromAPI = await mockAPI();
console.log(fromAPI);
}
async function handleClickAwaitBetween() {
console.clear();
console.log("Calling 1st setState()");
updateBooleanState(false);
// AWAIT CALL RUNS BETWEEN THE setState CALLS
const fromAPI = await mockAPI();
console.log(fromAPI);
console.log("Calling 2nd setState()");
updateBooleanState(true);
console.log("After 2nd setState()");
}
This is the result:
Comments
We can see that the setState() calls are batched if there are no await calls (Click Normal) and if the await call comes after the setState() (Click Await After).
And that the setState() calls are NOT batched if there's an await call before (Click Await Before) or between the setState() calls (Click Await Between).
