为了账号安全,请及时绑定邮箱和手机立即绑定

如果在事件处理程序之前或之间有 await 调用,React 将不会在事件处理程序中批处

如果在事件处理程序之前或之间有 await 调用,React 将不会在事件处理程序中批处

浮云间 2021-06-29 14:50:41
我发现了这个有趣的 React 行为,我想了解更多。通常 React 会setState()在事件处理程序中批处理多个调用,对吗?但我测试了 React 在以下情况下不会批量调用:事件处理函数是一个async带有await调用的函数。和await呼叫执行之前或之间的setState()通话。如果在调用await之后运行setState(),它们会像往常一样批处理。问题:你知道这背后的原因是什么吗?CodeSandbox: 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()");  }这是结果:
查看完整描述

2 回答

?
慕尼黑8549860

TA贡献1818条经验 获得超11个赞

首先,让我们看看丹·阿布拉莫夫对这件事是怎么说的:

在当前版本中,如果您在 React 事件处理程序中,它们将被批处理。React 批处理在 React 事件处理程序期间完成的所有 setState,并在退出自己的浏览器事件处理程序之前应用它们。

在当前版本中,事件处理程序之外的几个 setStates(例如在网络响应中)将不会被批处理。所以在这种情况下你会得到两次重新渲染。

嗯,所以我们可以从 React 事件处理程序及其外部执行 setState 。React 事件处理程序是我们作为 prop 传递给组件的函数。

如果我们在handleClickAwaitBefore没有 async-await 的情况下获取并重写它,我们会得到这样的结果:

 function handleClickAwaitBefore() {

    console.clear();


    // Here we are in event handler and setState is batched

    mockAPI().then(function notEventHandlerAnyMore(){

       

       // Here we are in totally different function and setState is not batched any more

       console.log(fromAPI);


       console.log("Calling 1st setState()");

       updateBooleanState(false);


       console.log("Calling 2nd setState()");

       updateBooleanState(true);


       console.log("After 2nd setState()"); 

    })


  }


查看完整回答
反对 回复 2021-07-01
  • 2 回答
  • 0 关注
  • 165 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信