我发现了这个有趣的 React 行为,我想了解更多。
通常 React 会在事件处理程序中批处理多个 setState()
调用,对吗?
但我测试过 React 在以下情况下不会批处理调用:
- 事件处理函数是一个带有
await
调用的async
函数。 await
调用在setState()
调用之前或之间执行。- 如果
await
在setState()
调用之后运行,它们将照常进行批处理。
- 如果
问题:
你知道这背后的原因是什么吗?
代码沙箱: https://codesandbox.io/s/eventhandlerawaitso-jsdxs
这是mockAPI
调用
function mockAPI() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("I come from API using an AWAIT call");
},500);
});
}
这些是要测试的处理程序:
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()");
}
这是结果:
评论
如果没有 await
调用,我们可以看到setState()
调用是批处理的(单击“正常”) 并且如果 await
调用在 setState()
之后 (单击 Await After)。
如果 await
调用 before (单击 Await Before),则 setState()
调用不会被批处理 或之间 setState()
调用(单击 Await Between)。
最佳答案
异步编程在很大程度上与调用堆栈和事件循环有关。
您可以在此视频中找到很多相关信息:https://www.youtube.com/watch?v=8aGhZQkoFbQ
因此,当您在两者之间有 await
时,setState
将落入不同的堆栈。
我相信这是 React 不对它们进行批处理的主要原因。
关于javascript - 如果在事件处理程序之前或之间有等待调用,React 不会在事件处理程序中批处理 setState 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56581542/