对 useEffect 钩子内的多个 setState() 调用进行批量更新 [英] React batch updates for multiple setState() calls inside useEffect hook

查看:125
本文介绍了对 useEffect 钩子内的多个 setState() 调用进行批量更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在丹·阿布拉莫夫 (Dan Abramov) 的这个回答中,我发现了以下内容:

On this answer by Dan Abramov here on SO, I've found out the following:

React 是否保持状态更新的顺序?

目前(React 16 及更早版本),默认情况下仅对 React 事件处理程序内部的更新进行批处理. 有一个不稳定的 API 可以在您需要的极少数情况下强制在事件处理程序外部进行批处理.

Currently (React 16 and earlier), only updates inside React event handlers are batched by default. There is an unstable API to force batching outside of event handlers for rare cases when you need it.

他还在这个 Github 问题中提到了这一点:

He also mentions that in this Github issue:

https://github.com/facebook/react/issues/10231#issuecomment-316644950

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

In current release, they will be batched together if you are inside a React event handler. React batches all setStates done during a React event handler, and applies them just before exiting its own browser event handler.

但事实是,这个片段似乎证明useEffect() 内多个 setState 调用的更新是批处理的.

But the fact is that this snippet seems to prove that updates for multiple setState calls inside a useEffect() are batched.

问题

React 是否也总是为 useEffect 内的多个 setState() 调用批量更新?它还有什么地方可以做到这一点?

Does React also always batch updates for multiple setState() calls inside useEffect ? Where else does it do that ?

注意:根据他的回答,在下一个主要版本(可能是 v17)默认情况下,React 将在任何地方进行批处理.

NOTE: According to his answers, on next major release (probably v17) React will batch everywhere by default.

SNIPPET:在带有多个 setState() 调用的 useEffect() 内批量更新

SNIPPET: batch updates inside a useEffect() with multiple setState() calls

function App() {

  console.log('Rendering app...');
  
  const [myState,setMyState] = React.useState(0);
  const [booleanState, setBooleanState] = React.useState(false);
  
  console.log('myState: ' + myState);
  console.log('booleanState: ' + booleanState);
  
  React.useEffect(()=>{
    console.log('Inside useEffect...');
    setMyState(1);
    setMyState((prevState) => prevState +1);
    setMyState(3);
    setMyState(4);
    setMyState(5);
    setBooleanState(true);
  },[]);

  return(
    <div>App - Check out my console!</div>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

推荐答案

好问题.以下是完成@FranklinOcean 回答的其他信息.

Nice question. Here is additional info to complete @FranklinOcean answer.

2021 年更新:React 18 即将发生的变化

请参阅 React 18 中有关此主题的 Dan Abramov 更新,该主题添加了自动批处理:https://github.com/reactwg/react-18/discussions/21

Please see Dan Abramov update concerning this topic in React 18, which is the one that adds automatic batching: https://github.com/reactwg/react-18/discussions/21

回答当前版本的 react,即 17.0.2 及以下,截至 2021 年.

基于基于以下代码和框:

批量setStuff调用:

Batched setStuff calls:

  • 同步内联组件功能块(我觉得相当于一个效果先于其他效果运行,没有依赖关系)
  • 在一个 useEffect 块中同步
  • 在合成事件处理程序中同步(由react管理,例如onClick={handlerFunction})
  • Inline the component function block synchronously (I think it is equivalent to having an effect running before the other effects and without dependencies)
  • In a useEffect block synchronously
  • In a synthetic event handler synchronously (managed by react, such as onClick={handlerFunction})

每次都会触发重新渲染的非批量调用:

  • 任何异步代码(上述任何用例中的承诺/异步函数)
  • 非合成事件(在 react lib 之外管理的事件)
  • 这包括 XHR 或其他网络回调

我将尝试使用未来版本的 react 重新运行沙箱,看看效果如何!

I'll try re-run the sandbox with future versions of react to see how it goes!

这篇关于对 useEffect 钩子内的多个 setState() 调用进行批量更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆