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

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

1. 前言

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

2. react18之前

  • setState在不同情况下可以表现为异步或同步
  1. Promise的状态更新、js原生事件、setTimeout、setInterval中是同步的。
  2. 在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 批处理减少渲染次数 官方交流多看看


初心

我所有的文章都只是基于入门,初步的了解;是自己的知识体系梳理,如有错误,道友们一起沟通交流;
如果能帮助到有缘人,非常的荣幸,一切为了部落的崛起;
共勉
相关文章
|
3月前
|
前端开发 JavaScript
学习react基础(3)_setState、state、jsx、使用ref的几种形式
本文探讨了React中this.setState和this.state的区别,以及React的核心概念,包括核心库的使用、JSX语法、类与函数组件的区别、事件处理和ref的使用。
91 3
学习react基础(3)_setState、state、jsx、使用ref的几种形式
|
4月前
|
资源调度 前端开发 API
React Suspense与Concurrent Mode:异步渲染的未来
React的Suspense与Concurrent Mode是16.8版后引入的功能,旨在改善用户体验与性能。Suspense组件作为异步边界,允许子组件在数据加载完成前显示占位符,结合React.lazy实现懒加载,优化资源调度。Concurrent Mode则通过并发渲染与智能调度提升应用响应性,支持时间分片和优先级调度,确保即使处理复杂任务时UI仍流畅。二者结合使用,能显著提高应用效率与交互体验,尤其适用于数据驱动的应用场景。
86 20
|
4月前
|
存储 前端开发 JavaScript
处理 React 应用程序中的异步数据加载
【8月更文挑战第31天】
76 0
|
5月前
|
存储 前端开发 安全
|
6月前
|
前端开发
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
|
5月前
|
前端开发 JavaScript
react18【系列实用教程】useState —— 声明响应式变量(2024最新版)含useState 的异步更新机制,更新的合并,函数传参获取更新值,不同版本异步更新差异,更新对象和数组
react18【系列实用教程】useState —— 声明响应式变量(2024最新版)含useState 的异步更新机制,更新的合并,函数传参获取更新值,不同版本异步更新差异,更新对象和数组
304 0
|
7月前
|
前端开发
说说React中setState和replaceState的区别?
在 React 中,setState()和 replaceState()是用于更新组件状态的两个方法。它们之间有一些区别
57 0
|
前端开发 UED
react学习系列6 react-router 实现异步按需加载模块
按需加载模块的目的是实现代码分隔,用户打开首页时不用下载全部的代码,打开特定的页面加载特定的代码。提高用户体验。 如果使用的是react-router,官网文档给出的 方案 是用webpack的bundle-loader 你可能也见过require.ensure。
1288 0
|
7月前
|
设计模式 前端开发 数据可视化
【第4期】一文了解React UI 组件库
【第4期】一文了解React UI 组件库
386 0
|
7月前
|
资源调度 前端开发 JavaScript
React 的antd-mobile 组件库,嵌套路由
React 的antd-mobile 组件库,嵌套路由
132 0