猿问

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

我发现了这个有趣的 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()");

  }

这是结果:

浮云间
浏览 166回答 2
2回答

慕尼黑8549860

首先,让我们看看丹·阿布拉莫夫对这件事是怎么说的:在当前版本中,如果您在 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()");     })  }
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答