美文网首页React
React 中 setState 什么时候是同步的,什么时候是异

React 中 setState 什么时候是同步的,什么时候是异

作者: 云高风轻 | 来源:发表于2023-07-02 08:35 被阅读0次

1. 前言

  1. React 中 setState 什么时候是同步的,什么时候是异步的
  2. 这个问题之前不少道友问过,因为在我们的印象中这个都是当做异步来解释的
  3. 今天就来深入下,玩玩

2. react18之前

  • setState在不同情况下可以表现为异步或同步
  1. Promise的状态更新、js原生事件、setTimeout、setInterval中是同步的。
  1. 在react的合成事件中,是异步

3. react18之后。

  • setState都会表现为异步(即批处理)。
  1. 批处理:是指 React将多个状态更新分组到单个重新渲染中以获得更好的性能
  2. 如果同一点击事件中有两个状态更新,React 总是将它们批处理为一次重新渲染。如果运行以下代码,您将看到每次单击时,尽管您设置了两次状态,React 只执行一次渲染
function App() {
  const [count, setCount] = useState(0);
  const [flag, setFlag] = useState(false);

  function handleClick() {
    setCount(c => c + 1); // Does not re-render yet
    setFlag(f => !f); // Does not re-render yet
    // React will only re-render once at the end (that's batching!)
  }

  return (
    <div>
      <button onClick={handleClick}>Next</button>
      <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
    </div>
  );
}

4. react18之前 为啥不确定同步异步呢

  1. 在React中,如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用setState不会同步更新this.state,除此之外的setState调用会同步执行this.state 。
  2. 所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用

  • 原因:
  1. 在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,
  2. isBatchingUpdates默认是false,也就表示setState会同步更新this.state,
  3. 但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,
  4. 而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state。

  • 注意:
  1. setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,
  2. 只是合成事件钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,
    3 .当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。
  • 总结
  1. setState 只在合成事件和 hook() 中是“异步”的,在 原生事件和 setTimeout 中都是同步的。


参考资料

react18 批处理减少渲染次数 官方交流多看看


初心

我所有的文章都只是基于入门,初步的了解;是自己的知识体系梳理,如有错误,道友们一起沟通交流;
如果能帮助到有缘人,非常的荣幸,一切为了部落的崛起;
共勉

相关文章

网友评论

    本文标题:React 中 setState 什么时候是同步的,什么时候是异

    本文链接:https://www.haomeiwen.com/subject/wiozydtx.html