Javascript 异步事件处理程序中的setState更新是否成批进行?

Javascript 异步事件处理程序中的setState更新是否成批进行?,javascript,reactjs,async-await,dom-events,setstate,Javascript,Reactjs,Async Await,Dom Events,Setstate,根据我在reactversion16(当前)及以下版本中的理解,setState调用在组件生命周期事件或事件处理程序中进行时进行批处理。否则,为了批处理调用,有一个opt-inReactDOM。可以使用不稳定的批处理更新 但是,如果事件处理程序是一个async函数,浏览器将启动事件处理程序,但随后将返回一个承诺,因此实际的事件处理程序promise回调将在事件循环中拾取下一个微任务之前不会运行。换句话说,setState更新实际上并不发生在即时事件处理程序中 这是否意味着如果我们想在事件处理程序

根据我在
react
version16(当前)及以下版本中的理解,
setState
调用在组件生命周期事件或事件处理程序中进行时进行批处理。否则,为了批处理调用,有一个opt-in
ReactDOM。可以使用不稳定的批处理更新

但是,如果事件处理程序是一个
async
函数,浏览器将启动事件处理程序,但随后将返回一个承诺,因此实际的事件处理程序
promise
回调将在事件循环中拾取下一个微任务之前不会运行。换句话说,
setState
更新实际上并不发生在即时事件处理程序中


这是否意味着如果我们想在事件处理程序中批处理
setState
更新,我们需要选择进入
ReactDOM.unstable\u batchedUpdate

下面的调用将由React批处理,并将导致单次重新渲染

const onClick = (e) => {
    setHeader('Some Header');
    setTitle('Some Tooltip');
};
如果没有
ReactDOM.unstable\u batchedUpdate
,React将进行2次
sync
调用以重新渲染组件。现在,它将使用此API进行单次重新渲染

const onClick = (e) => {
    axios.get('someurl').then(response => {
        ReactDOM.unstable_batchedUpdates(() => {
            setHeader('Some Header');
            setTitle('Some Tooltip');
        });
    });
};
补充说明:

  • 我们在我们的项目中使用过一次,它工作得天衣无缝。但我个人更喜欢将状态作为对象并立即更新,而不是这种方法。但我明白这并不总是可能的
  • 我们可以看到它处于实验模式,所以不确定是否应该在生产中使用它
  • 更新

    根据OP注释,下面是JavaScript中async await的版本

    const onClick = async e => {
    
      setState(1);
      setState(2);
      await apiCall();
    
      ReactDOM.unstable_batchedUpdates(() => {
          setState(3);
          setState(4);
      });
    }
    

    上述代码将触发重新渲染2次。一次用于更新1/2,另一次用于更新3/4。

    下面的调用将由React进行批处理,并将导致单次重新渲染

    const onClick = (e) => {
        setHeader('Some Header');
        setTitle('Some Tooltip');
    };
    
    如果没有
    ReactDOM.unstable\u batchedUpdate
    ,React将进行2次
    sync
    调用以重新渲染组件。现在,它将使用此API进行单次重新渲染

    const onClick = (e) => {
        axios.get('someurl').then(response => {
            ReactDOM.unstable_batchedUpdates(() => {
                setHeader('Some Header');
                setTitle('Some Tooltip');
            });
        });
    };
    
    补充说明:

  • 我们在我们的项目中使用过一次,它工作得天衣无缝。但我个人更喜欢将状态作为对象并立即更新,而不是这种方法。但我明白这并不总是可能的
  • 我们可以看到它处于实验模式,所以不确定是否应该在生产中使用它
  • 更新

    根据OP注释,下面是JavaScript中async await的版本

    const onClick = async e => {
    
      setState(1);
      setState(2);
      await apiCall();
    
      ReactDOM.unstable_batchedUpdates(() => {
          setState(3);
          setState(4);
      });
    }
    

    上述代码将触发重新渲染2次。一次用于更新1/2,另一次用于更新3/4。

    经过研究,我相信答案是
    异步
    事件处理程序的初始部分(最终转换为
    承诺
    的执行器函数,该函数在引擎盖下返回)将批量进行
    设置状态
    更新,但在任何
    等待
    呼叫后,都不会执行任何操作

    这是因为在第一个
    wait
    之前的
    async
    函数体中的所有内容都被转换为executor函数,该函数在浏览器事件处理程序中为该事件执行,但之后的所有内容都作为初始executor函数的链式
    Promise
    回调结束,这些链式回调在微任务队列上执行

    这是因为
    async()=>{}
    被转换为类似
    returnnewpromise().then()
    的内容,其中每个then都是在
    wait
    语句之后为代码创建的回调

    const onClick = async e => {
      // 1 and 2 will be batched
      setState(1)
      setState(2)
    
      await apiCall()
    
      // 3 and 4 will not be batched
      setState(3)
      setState(4)
    }
    

    经过研究,我相信答案是
    async
    事件处理程序的初始部分(最终转换为在引擎盖下返回的
    Promise
    的executor函数)将批处理
    setState
    更新,但不会在任何
    等待
    调用之后进行任何操作

    这是因为在第一个
    wait
    之前的
    async
    函数体中的所有内容都被转换为executor函数,该函数在浏览器事件处理程序中为该事件执行,但之后的所有内容都作为初始executor函数的链式
    Promise
    回调结束,这些链式回调在微任务队列上执行

    这是因为
    async()=>{}
    被转换为类似
    returnnewpromise().then()
    的内容,其中每个then都是在
    wait
    语句之后为代码创建的回调

    const onClick = async e => {
      // 1 and 2 will be batched
      setState(1)
      setState(2)
    
      await apiCall()
    
      // 3 and 4 will not be batched
      setState(3)
      setState(4)
    }
    

    这不涉及
    async
    事件处理程序部分。@AdamThompson对于在事件处理程序返回(async)后执行的设置程序,答案是否定的,除非您将其包装在
    ReactDOM中。不稳定的批处理程序更新
    。API的事件处理程序是
    async
    。你也可以解决一个直接的承诺。我认为那应该掩盖你的要求。如果我误解了这里的任何内容,请提供一点澄清。请参阅我发布的答案,答案是,在
    async
    事件处理程序中,在第一个
    wait
    之前的任何内容都应该进行批处理-如果我缺少任何内容,请更正我。这并不能解决
    async
    事件处理程序部分。@AdamThompson对于在事件处理程序返回(async)之后执行的设置程序,答案是“否”除非将其包装在
    ReactDOM.unstable\u batchedUpdate
    中。API的事件处理程序是
    async
    。你也可以解决一个直接的承诺。我认为那应该掩盖你的要求。如果我误解了这里的任何内容,请提供一点澄清。请参阅我发布的答案,答案是
    async
    事件处理程序中第一个
    wait
    之前的任何内容都应该进行批处理-如果我遗漏了任何内容,请纠正我。