一、批处理

批处理是 React将多个状态更新分组到单个re-render中以获得更好的性能的操作。

例如,如果你在同一个点击事件中有两个状态更新,React 总是将它们分批处理到一个重新渲染中。如果你运行下面的代码,你会看到每次点击时,React 只执行一次渲染,尽管你设置了两次状态:

function App() {const [count, setCount] = useState(0);const [flag, setFlag] = useState(false);function handleClick() {setCount(c => c + 1); // Does not re-render yetsetFlag(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>);
}

这对性能非常有用,因为它避免了不必要的重新渲染。它还可以防止您的组件呈现仅更新一个状态变量的“半完成”状态,这可能会导致错误。

在 React 18 之前,我们只在 React 事件处理程序期间批量更新。默认情况下,React 中不会对 promise、setTimeout、原生事件处理(native event handlers)或其它React默认不进行批处理的事件进行批处理操作。

二、setState 的批处理

React 18 之前

在 React 18 之前,React 只能在组件的生命周期函数或者合成事件函数中进行批处理。

默认情况下,Promise、setTimeout 以及原生事件中是不会对其进行批处理的。如果需要保持批处理,则可以用 unstable_batchedUpdates 来实现,但它不是一个正式的 API。

handleClick = () => {setTimeout(() => {console.log('setTimeout 更新之前:', this.state.num); // 0this.setState(state => ({ num: state.num + 1 }))console.log('setTimeout 更新之后:', this.state.num); // 1})
}
import ReactDOM from 'react-dom'
const { unstable_batchedUpdates } = ReactDOMhandleClick = () => {setTimeout(() => {unstable_batchedUpdates(()=>{console.log('setTimeout 更新之前:', this.state.num); // 0this.setState(state => ({ num: state.num + 1 }))console.log('setTimeout 更新之后:', this.state.num); // 0})})
}

React 18 之后

从 React 18的createRoot开始,所有更新都将自动批处理,无论它们来自何处。

这意味着timeouts, promises, native event handlers或任何其他事件内的更新将以与 React 事件内的更新相同的方式进行批处理。

handleClick = () => {setTimeout(() => {console.log('setTimeout 更新之前:', this.state.num); // 0this.setState(state => ({ num: state.num + 1 }))console.log('setTimeout 更新之后:', this.state.num); // 0})
}

如果想在 React 18 退出批处理,官方提供了一个 API flushSync。

import { flushSync } from 'react-dom'; // Note: react-dom, not reactfunction handleClick() {flushSync(() => {setCounter(c => c + 1);});// React has updated the DOM by nowflushSync(() => {setFlag(f => !f);});// React has updated the DOM by now
}

三、React 的渲染模式

React 批处理方式的改变,主要是因为改变了渲染模式,React 目前有三种渲染模式

  1. legacy 模式:ReactDOM.render(<App />, rootNode)。React 18 前的设计模式,这将创建一个以“遗留”模式运行的 root。使用此 API 会有一个警告,表明它已被弃用并切换到 New Root API。
  2. blocking 模式:ReactDOM.createBlockingRoot(rootNode).render(<App />) 。可以视为 concurrent 的优雅降级版本和过渡版本
  3. concurrent 模式 :ReactDOM.createRoot(rootNode).render(<App />)。这将创建一个在 React 18 中运行的 root,它添加了 React 18 的所有改进并允许使用并发功能。React 18 采用的模式,拥有不同的优先级,更新的过程可以被打断。

legacy 模式,根据 isBatchUpdate 判断是否批量更新,在 React 事件中有自动处理批更新的功能。非 React 事件想使用这个功能必须使用 unstable_batchedUpdates。

concurrent 模式,是以优先级为依据对更新进行合并的。 每次更新会进行优先级的判定,相同优先级的任务会被合并,所有的 setState 在默认情况下都是批处理更新的。


参考链接:
Automatic batching for fewer renders in React 18
Automatic Batching in React 18: What You Should Know
一探那些令人興奮的 React 18 三大新 features
React18 setState之 Automatic batching
一篇带给你 React 18 升级指南

React - React v18 的 批处理相关推荐

  1. [react] react中除了在构造函数中绑定this,还有别的方式吗?

    [react] react中除了在构造函数中绑定this,还有别的方式吗? 1:函数定义的时候使用箭头函数 2:函数调用是使用bind绑定this 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放 ...

  2. [react] react是什么?它的主要特点是什么?

    [react] react是什么?它的主要特点是什么? React是用于构建用户界面的库. 特点: 组件化,增强复用性 数据到视图的单向绑定,更安全 数据的单项传递流 高性能 个人简介 我是歌谣,欢迎 ...

  3. [react] react中可以在render访问refs吗?为什么?

    [react] react中可以在render访问refs吗?为什么? <><span id="name" ref={this.spanRef}>{this ...

  4. [react] react兄弟组件如何通信?

    [react] react兄弟组件如何通信? 状态提升,通过父组件的state和方法传递到两个子组件 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷.欢迎大家一起讨论 ...

  5. [react] react声明组件有哪几种方法,各有什么不同?

    [react] react声明组件有哪几种方法,各有什么不同? 1.无状态组件 2.有状态组件 3.高阶组件 4.容器组件 5.回调组件 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, ...

  6. [react] react组件间的通信有哪些?

    [react] react组件间的通信有哪些? Props Context ref:通过Ref获取组建的实例,在通过实例拿到组件的属性值或者方法的回调 第三方的,Redux是基于Conext基础上的库 ...

  7. [react] react怎么拿到组件对应的DOM元素?

    [react] react怎么拿到组件对应的DOM元素? 在Class组件中 import React from 'react'; class CComponent extends React.Com ...

  8. [react] react是哪个公司开发的

    [react] react是哪个公司开发的 facebook 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷.欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

  9. [react] react的mixins有什么作用?适用于什么场景?

    [react] react的mixins有什么作用?适用于什么场景? 1.mixin的作用是抽离公共功能,不存在渲染dom的需要,所以它没有render方法.如果你定义了render方法,那么他会和组 ...

最新文章

  1. ADF12C 在线预览PDF文件 afinlineFrame
  2. 深度学习(计算机视觉方向)小白入门的一些建议
  3. C# .net 命名规范
  4. fz响应无法连接到服务器,fz链接不到服务器
  5. 浅谈Java中equals()和==的区别
  6. [转载] 大道至简:软件工程实践者的思想——第十章 是思考还是思想
  7. 代码改变世界,也改变了我
  8. 计算机网络应用押韵句,现代汉语练习题
  9. IDEA 2020.3 连接mysql数据库报错解决
  10. SpringBoot的启动过程
  11. 计算机单词 硬件类、软件类、网络类、其他
  12. Microchip PIC系列8位单片机入门教程(五)定时器
  13. wav格式怎么转换成flac?
  14. 考研英语 常见不规则动词过去式/过去分词
  15. Android实现Twitter登录分享
  16. 宋词10家--一人一首成名曲
  17. 计算机格式为gpt怎么更改,硬盘格式转换,手把手教你如何将硬盘mbr格式转换为gpt格式...
  18. 安装 Ubuntu 操作系统步骤教程
  19. 关于ASP使用服务器采集文章及图片
  20. 她二本科毕业,拿到阿里年薪40万offer!经验都记录在这几个公众号日记中

热门文章

  1. PyCharm默认快捷键(系统默认最全)中英文版 DEFAULT KEYMAP(PyCharm 2018.1) 个人翻译
  2. minixml的安装教程
  3. 让Windows 7自动显示详细登录时间
  4. 盘点企业直播公司的选择误区
  5. 基于Android平台实现x的跑步应用App设计【附项目源码+论文说明】分享
  6. linux恢复初始环境变量,linux 环境变量恢复默认值
  7. QTableView样式表实战
  8. 胶囊网络(Capsule)学习笔记
  9. win10系统无法调节亮度
  10. Calabash探索1-Run Calabash