React16源码: React中调度之batchedUpdates的源码实现

React 18 新特性(一):自动批量更新 本文介绍了 React 18 的自动批量更新特性,和之前版本的批量更新进行了对比。并且使用代码模拟了批量更新的不同实现思路。 阅读详情

batchedUpdates


1 )概述

  • 在 requestWork 在中间, 会判断一个 isBatchingUpdates 做一些特定的操作
  • batchedUpdates 是一个批量更新的操作, 什么是批量更新呢?先来看一个例子

2 )示例

index.js

import React from 'react'
import ReactDOM from 'react-dom'

import App from './demos/batchedUpdates'

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

demos/batchedUpdates

import React from 'react'
import { unstable_batchedUpdates as batchedUpdates } from 'react-dom'

export default class BatchedDemo extends React.Component {
  state = {
    number: 0,
  }

  handleClick = () => {
    // 第一种场景 事件处理函数自带`batchedUpdates`
    // this.countNumber()

    // 第二种场景,主动`batchedUpdates`
    // setTimeout(() => {
    //   this.countNumber()
    // }, 0)

    // 第三种场景,setTimeout中没有`batchedUpdates`
    setTimeout(() => {
      batchedUpdates(() => this.countNumber())
    }, 0)
  }

  countNumber() {
    const num = this.state.number
    this.setState({
      number: num + 1,
    })
    console.log(this.state.number)
    this.setState({
      number: num + 2,
    })
    console.log(this.state.number)
    this.setState({
      number: num + 3,
    })
    console.log(this.state.number)
  }

  render() {
    return <button onClick={this.handleClick}>Num: {this.state.number}</button>
  }
}
  • 在上述 countNumber 中定义了更改 state的方法
  • 当点击 按钮时,里面的 num 会更改,回调函数是 handleClick
    • 第一种情况
      • 当直接调用 countNumber 时,页面显示 3,但是 console 面板分别输出 3次0
      • 注意 只获取一次 num, 初始化是 0,执行了3次setState, 最后一次是 0 + 3 = 3
      • 这是因为 batchUpdtes 的概念所导致
    • 第二种情况
      • 在一个延迟器中调用 countNumber
      • 这时候页面显示 3,console面板中分别输出 1, 2, 3
      • 这是我们符合预期的输出
    • 第三种情况
      • 在延迟器中使用 batchedUpdates 这个 API,来调用 countNumber
      • 这时候,页面显示 3,console面板 依次输出 3次0
  • 那么它(batchedUpdates)的原理是什么呢?

3 ) 源码

进入到 requestWork 函数中的相关判断,可以在源码 nodemodules/react-dom/cjs/react-dom-development.js 中
找到 requestWork 进行debugger,重启 react项目,之后在 Chrome 中调试

if (isBatchingUpdates) {
  // Flush work at the end of the batch.
  if (isUnbatchingUpdates) {
    // ...unless we're inside unbatchedUpdates, in which case we should
    // flush it now.
    nextFlushedRoot = root;
    nextFlushedExpirationTime = Sync;
    performWorkOnRoot(root, Sync, true);
  }
  return;
}
  • 第一种场景下

    • isBatchingUpdates 是 true, isUnbatchingUpdates 是 false
    • 这样,最终直接 return 了, 就没有进入后续的调度,就什么都没做
    • 通过调用堆栈可知,3个 update 调用完成后,存入 updateQueue之后
    • 会调用 performSyncWork 来帮助我们完成任务调度的过程,而非通过 requestWork 来完成的任务调度
    • 这样,任务更新队列就在一起把state更新了, 所以要等到 state 所有都变掉之后,才会执行state的更新
    • 所以 console 面板中打印的,不是真正更新后的 state
    • 这就是 batchUpdates 让我们在一个方法调用里面,所有的setState都是一次性更新到我们的state里面的
    • 而不是每次都调用 setState 进入调度和渲染,以此来提升性能效率
  • 第二种场景下

    • 当 setTimeout 执行后,方法执行上下文已不是 handleClick这个函数了,而是 window 了
    • 这时的 batchUpdates 已重置了
    • 这时候调用 countNumber 就没有 isBatchingUpdates 为 true 的情况了,就不会批量执行
    • 所以,每次 setState 都会更新,导致我们每次打印的都是新的 state
    • 这种会导致,我们的应用性能变得很低,所以这种是极不推荐的
  • 第三种场景下

    • 基于 batchedUpdates 的 API 调用 countNumber
    • 这个 API 的作用是 设置上下文,handleClick 是react里面的事件体系产生的回调
    • 事件体系会主动调用 batchedUpdates 或 interactiveUpdates 帮助我们设置上下文
    • 所以,在react事件中大部分回调都是会帮助我们做批量更新的
    • 而不会让我们在事件的回调中做多次的更新
    • 这是react 事件绑定中的性能优化

在 ReactFiberSchduler.js 中的 batchedUpdates 中

// TODO: Batching should be implemented at the renderer level, not inside
// the reconciler.
function batchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
  const previousIsBatchingUpdates = isBatchingUpdates;
  isBatchingUpdates = true;
  try {
    return fn(a);
  } finally {
    isBatchingUpdates = previousIsBatchingUpdates;
    if (!isBatchingUpdates && !isRendering) {
      performSyncWork();
    }
  }
}
  • 它设置 isBatchingUpdates = true;,在设置之前记录前值 const previousIsBatchingUpdates = isBatchingUpdates;
  • 当我们的回调 fn 被调用之后,在 finally 中 恢复 isBatchingUpdates 成之前的值 previousIsBatchingUpdates
  • 之后,判断是否符合 !isBatchingUpdates && !isRendering 符合了,则调用 performSyncWork 方法

同样,unbatchedUpdates 也是来自这个文件

// TODO: Batching should be implemented at the renderer level, not inside
// the reconciler.
function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
  if (isBatchingUpdates && !isUnbatchingUpdates) {
    isUnbatchingUpdates = true;
    try {
      return fn(a);
    } finally {
      isUnbatchingUpdates = false;
    }
  }
  return fn(a);
}
  • 它设置 isUnbatchingUpdates 为 true
  • 它也是上下文的关系,让我们在调用 fn 的时候有这么一个值是 true 的上下文
  • 标记产生的不一样的变化
  • 以上是批量更新的概念和原理
  • 扩展
    • 从上面我们知道 setState 这个方法是同步的,
    • 但是调用之后,并不标志 react 的状态立马更新
    • 这个更新是需要根据当前环境的上下文来判断的
    • 如果处于批量更新的情况下,state不是立马更新的
    • 如果不处于批量更新的情况下,state 可能会立马更新
      • 因为 有 ConcurrentMode 这种异步渲染的情况
      • 这种情况下,state 也不是立马就更新的
    • 进入异步更新,就会进入到异步调度的过程中
【React Hooks - useState状态批量更新原理】 通过demo示例结合Chrome调试的方式从源码角度介绍了React17、React18对于状态批量处理的原理 阅读详情

相关推荐

前端面试八股:技术认知的四层压力测试

前端面试八股并非死记硬背的题库,而是围绕JavaScript引擎、浏览器渲染管线、框架核心机制与工程化链路四大底层锚点构建的技术认知体检体系。其本质是通过术语识别、机制还原、边界穿透与架构映射四层结构,系统检验开发者对‘事件循环’‘响应式原理’等基础概念的理解深度与迁移能力。这类题目直指‘会用’与‘懂原理’之间的关键鸿沟,在真实业务场景(如长列表卡顿优化、并发请求控制)中持续暴露知识断层。掌握八股,就是构建可演化的前端技术坐标系,让每一次面试都成为认知升级的实证过程。

ckkay800264的博客 331

React 性能优化之批量处理 unstable_batchedUpdates

手动批量处理 unstable_batchedUpdates 可用于手动批量更新state,可以指定多个setState合并为一个更新请求。 import { useState, useLayoutEffect } from "react"; import * as ReactDOM from "react-dom"; function App() { const [count, setCount] = useState(0); const [flag, setFlag] = useState(

qq_33490514的博客 4746

Win10下ISE14.7 iMPACT闪退?三步搞定DLL替换(附详细路径)

本文详细介绍了在Windows 10系统下解决Xilinx ISE14.7 iMPACT工具闪退问题的三步DLL替换方案。通过替换关键DLL文件,有效解决了FPGA开发中的兼容性问题,帮助开发者快速恢复工作流程。

weixin_29290259的博客 589

React 18 中自动批处理以减少重复渲染

从 React 18 版本开始,会默认自动进行批处理(automatic batching),减少组件的重复渲染,以此提升性能。本篇文章主要介绍以下的内容:什么是批处理、它以前是如何工作的,以及现在发生了什么变化。......

码飞_CC的博客 2260

《揭秘 BME688人工智能压力湿度温度气体传感器:气体检测的多面能手》:此文为AI自动生成

BME688 是博世推出的一款具有人工智能和集成高线性度高精度压力、湿度、温度传感器的气体传感器,专为移动和联网应用开发,尺寸紧凑且低功耗。BME688 作为一款先进的传感器,在多个领域展现出卓越的性能。它采用了坚固而紧凑的 3.0 x 3.0 x 0.9 mm³ 封装,这种小巧的尺寸使其能够轻松应用于对空间要求严格的移动设备和联网应用中。同时,低功耗的特性也使得它在能源有限的环境下能够长时间稳定运行。

zheng_ruiguo的专栏 1939

微波技术仿真:微波谐振器分析_(2).微波谐振器理论

谐振器是一种能够在特定频率范围内存储和释放电磁能量的器件。在微波频段,谐振器通常用于滤波、频率选择和能量存储等应用。一个理想的谐振器在谐振频率下能够存储无限大的能量,但在实际应用中,由于损耗的存在,谐振器的性能会受到一定限制。微波谐振器在微波通信、雷达系统、微波测量和微波电路设计等领域中发挥着重要作用。谐振器的设计需要考虑多个因素,包括谐振频率的精确控制、损耗的最小化、频率稳定性的提高和小型化设计。通过理论分析和仿真工具的使用,可以有效优化谐振器的性能,满足实际应用的需求。

2401_87715305的博客 936

【译】React18 中会自动批量更新,达到更少的 render 次数

批量更新是指 React 的多个 state 在一个 re-render 里更新,以获得更好的性能。例如,如果在一个 click 事件中你有两个 state 更新,React 总是会批量更新它们在一个 re-render 里。如果你执行下面的代码,你将会看到每一次你点击,React 仅仅会执行一次 render,即使你设置了 state 两次。// 还不会 re-render setFlag(f =>!f);

m0_50823463的博客 976

03. 线性规划与混合整数规划 (LP/MIP)

本文介绍了OR-Tools中的线性规划(LP)和混合整数规划(MIP)求解器。主要内容包括:1) LP/MIP的基本概念和数学形式,对比了LP、MIP、ILP和BIP的区别;2) OR-Tools支持的求解器类型,如GLOP、SCIP等,以及它们各自的特点和适用场景;3) 详细展示了如何使用GLOP求解器进行线性规划求解,包括变量定义、约束添加和目标函数设置;4) 介绍了SCIP求解器的配置和使用方法;5) 讨论了变量类型、约束类型、多目标优化等进阶功能。文章通过Java代码示例演示了如何实现一个完整的优化

智慧是做事用的 158

just-react 并发模式指南:从入口函数到 Fiber 架构、Scheduler 与 lane 模型,理解 React Concurrent Mode 的底层实现

本文基于「React技术揭秘」仓库中 [docs/concurrent/prepare.md](https://link.gitcode.com/i/33780b2be1b49e99396ad961b1cd2c07) 一文展开。该文档是全书第八章《Concurrent Mode》的开篇总览,回答了三个核心问题:Concurrent 模式是什么、它为什么值得 React 花两年时间重构 Fiber

gitblog_01103的博客 890

虚拟机VMware Horizon Client与主机之间建立共享文件夹

因经常需要在虚拟机和主机之间传递一些日常文件,所以建立共享文件夹。 虚拟机中安装的系统为win10,主机中的系统为win10。 步骤: 第一步:先在虚拟机win10中新建文件夹(我重命名为“共享文件夹”),然后右键属性->共享->共享 进去之后点击自己的账户名 然后点共享。操作完成后,再返回属性界面就能看到该文件夹已经共享而且出现了共享链接,记下此链接。 第二步:回到主机桌面->此电脑->最上面计算机->添加一个网络位置- 点击下一步 然后自定义网络位置,下一步,如下图

AnChenliang_1002的博客 1万+

NL2SQL进阶系列(3):Data-Copilot、Chat2DB、Vanna Text2SQL优化框架开源应用实践详解[Text2SQL]

NL2SQL进阶系列(3):Data-Copilot、Chat2DB、Vanna Text2SQL优化框架开源应用实践详解[Text2SQL]

丨汀、的博客 5422

【笔记-react】《imooc-React源码深度解析 高级前端工程师必备技能》

第01章 课程导学 01-01 课程导学 一、UI=fn(x) 核心api:setState 没有directive双向绑定 二、vue,angular更新大版本,需要调整兼容 三、react,引入fiber,从根本上解决了,js单线程运行,如果计算量太大,导致动画卡帧,交互卡顿问题 四、第1章:React API,及每个API的作用 createElement、createContext、JSX=>JS、ConcurrentMode、Ref、Component、Suspense、Hooks 五、第2

aSuncat 1167

【unity实战】Unity游戏开发:如何用ScriptableObject与序列化多态实现可复用的模块化效果系统?

本文介绍了两种实现卡牌游戏效果系统的模块化设计方案。方案一使用ScriptableObject创建独立的效果资产,通过组合实现不同效果,优点是数据可复用、可视化编辑,缺点是同类不同参数效果需创建大量SO文件。方案二利用SerializeReference特性直接嵌套效果实例,避免SO文件过多,但需要插件支持编辑器多态显示。两种方案都将效果与卡牌解耦,提高了代码复用性和扩展性,解决了硬编码带来的重复、维护困难和扩展不便等问题。开发者可根据项目需求选择合适方案,或结合两者优势构建更灵活的系统。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 437

react源码解析16.concurrent模式

react源码解析16.concurrent模式 视频讲解(高效学习):进入学习 concurrent mode react17支持concurrent mode,这种模式的根本目的是为了让应用保持cpu和io的快速响应,它是一组新功能,包括Fiber、Scheduler、Lane,可以根据用户硬件性能和网络状况调整应用的响应速度,核心就是为了实现异步可中断的更新。concurrent mode也是未来react主要迭代的方向。 cup:让耗时的reconcile的过程能让出js的执行权给更高优先级的任务

zz1999aa的博客 331

3D 韩系风格漫剧人设 | GPT-Image2 人设生成【附完整提示词】

宁姚同款清冷剑系美人,极致小巧鹅蛋脸,下颌线紧致纤细流畅,下巴小巧精致收窄,小脸衬得五官格外舒展,韩式水光肌,面部精细水光高光,鼻梁高光、鼻尖高光、面中苹果肌高光、唇珠高光,红棕色长卷发偏分大波浪,垂在一侧肩前,发量蓬松。发量丰厚蓬松有体积感,不贴头皮,几缕碎发自然垂落脸侧修饰脸型,长度过胸及背,发丝柔顺丝滑卷度自然,发尾自然垂落,身穿香槟色缎面挂脖长裙,挂脖设计无袖露肩露背,上半身围裹式荡领胸口垂褶,腰部堆褶收腰,修身直筒包臀裙长度到脚踝,缎面光泽感强垂坠感好,极简剪裁。纯白色背景,3D漫剧写实厚涂风。

欢迎来到鸾姝淡月博客,专为程序员和编程爱好者打造的技术博客。我们分享编程语言趋势、开发工具、编程哲学、职业发展等,助你掌握新技术,优化技能,激发编程热情。 151

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

ACE-Step UI 本地部署教程:把自有 GPU 变成免费 AI 音乐工作室

还在为每首 AI 歌曲付订阅费、受生成次数限制吗?ACE-Step UI 是一款免费开源的 AI 音乐生成工具,它在你本地电脑上运行开源的 ACE-Step 1.5 模型,输入歌词和风格描述,就能无限次生成带人声的完整歌曲——数据全程不出设备,作品完全归你所有。 [![ACE-Step UI 主界面演示:本地 AI 音乐生成创作流程](https://raw.gitcode.com/GitHub

gitblog_00307的博客 696

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

React 技术揭秘:React16 的三层架构(Scheduler-Reconciler-Renderer)如何支撑异步可中断更新

> 本文基于「React 技术揭秘」仓库 [docs/preparation/newConstructure.md](https://link.gitcode.com/i/2f46e28e79a56eaedddcb9e1b671ad21) 展开,并融合仓库内 [docs/preparation/oldConstructure.md](https://link.gitcode.com/i/52895

gitblog_00842的博客 366

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

GetQzonehistory 快速上手:把 QQ 空间历史说说导出成本地 Excel

QQ 空间首页翻不到几年前的动态,想给老账号做一次备份却找不到入口。GetQzonehistory 是一个跑在自己电脑上的 Python 脚本,扫码登录后批量拉取历史消息,最终把 QQ 空间历史说说导出成 Excel 表格和网页,所有文件只留在本机。 ## 它是什么 - 📁 运行位置:纯本地命令行程序,解析、分类、落盘全部发生在你的电脑上; - 登录方式:手机 QQ 扫码,全程不输密码; -

gitblog_00466的博客 218

react源码解析6.legacy模式和concurrent模式

react源码解析6.legacy模式和concurrent模式 视频讲解(高效学习):点击学习 课程目录: 1.开篇介绍和面试题 2.react的设计理念 3.react源码架构 4.源码目录结构和调试 5.jsx&核心api 6.legacy和concurrent模式入口函数 7.Fiber架构 8.render阶段 9.diff算法 10.commit阶段 11.生命周期 12.状态更新流程 13.hooks源码 14.手写hooks 15.scheduler&Lane 16.conc

潇晨1998的博客 239

React面试题笔记(一)

React面试题笔记(一)

qq_42750608的博客 1249

ReactDom.unstable_batchedupdates(React处理批量更新)

React中不稳定的批量更新处理 import React, { useState } from 'react'; import { unstable_batchedupdates } from 'react-dom'; export default function Demo() { const [name, setName] = useState(''); const [age, setAge] = useState(12); useEffect(() => { unstable_.

张鹏~IT~少年人的博客 1306

React中setState更新机制、batchUpdate机制和transaction事务机制

React中setState的有关问题 1、react的setState是如何更新的? 2、setState是同步的还是异步的? 3、setState什么时候合并,什么时候不合并? 核心要点: 1、react的setState是如何更新的? setStated的执行原理: setState接收一个新的状态 该接收到的新状态不会被立即执行么,而是存入到pendingStates(等待队列)中 判断isBatchingUpdates(是否是批量更新模式) 1>. isBatchingUpdate

祥哥的说 4217

React Hooks批量更新问题

React 17.0.2 log会打次2次,也就是对于同一状态同时多次修改,那么React会合并一起更改,log打印两次是因为在开发环境下,会多执行一次。每次点击button ,log会执行3次,当我们把async方法里面的await去掉,让他变成正常方法,那么点击button就会执行一次。React 17.0.2 在异步方法中,多个状态同时修改会造成页面刷新多次,同一状态同时多次修改页面只会刷新一次。同样代码在React 版本18.2.0时候点击button,log只会打印一次。

qq_33715850的博客 869

React 批量更新

一些组件也许想要更新状态来响应同一事件。下面这个例子是假设的,但是却说明了一个常见的模式: 当事件被触发时,子组件的 onClick 首先被触发(同时触发了它的 setState )。然后父组件在它自己的 onClick 中调用 setState 。如果 React 立即重渲染组件以响应 setState 调用,最终我们会重渲染子组件两次: 第一次 Child 组件渲染是浪费的。并且我们也不会让 React 跳过 Child 的第二次渲染因为 Parent 可能会传递不同的数据由于其自身的状态更新。这就是为

weixin_43484007的博客 1081

说一下我理解的 React - batchUpdate 机制

batchUpdate 机制(批量更新机制)是理解 React 组件更新流程的重点,要搞清楚主要流程。 梳理这篇博客,来帮助我更好地理解和记忆,水平有限,看到的同学如有发现讲的不对的地方,烦请指正。

shenjing_Shining的博客 1686

react div onclick叠加_深入 react 细节之 - batchUpdate

实验作为 react 的用户,大家多多少少听说过 react 会有 batch update 的策略,那具体是怎样的呢?我们写个 demo:代码 https://codesandbox.io/s/48lp729k80预览地址:https://48lp729k80.codesandbox.io/大家可以点开上面的预览地址试一下,这三个 button 的 handelr 内部都以不同形式执行了两次 s...

weixin_39644614的博客 278
上一篇: React16源码: React中调度之requestWork的源码实现
下一篇: React16源码: React中的异步调度scheduler模块的源码实现
Wang's Blog
博客等级 码龄12年 7434粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值