React16源码: ConcurrentMode的使用及源码实现

深入理解 React 并发模式(Concurrent Mode):原理、优势与实践 React 团队在 React 18 中引入了 并发模式(Concurrent Mode),这是一项革命性的改进,旨在通过可中断渲染和优先级调度,使应用更加高效和用户友好。本文将深入探讨并发模式的原理、核心 API、使用场景,并通过代码示例展示如何在实际项目中应用它。 阅读详情

ConcurrentMode

1 ) 概述

  • ConcurrentMode 是 React 16 出来的一个最令人振奋的功能
  • 在2018年年初是 Async Mode,在发布了16.6之后,名字进行了更新
  • 然后改成了 ConcurrentMode,中间的API有一个过渡的版本,后续会提到
  • 它其实是 React 16 之前已有的概念了
  • 其目标是让 React 的整体渲染过程能够进行一个优先级的排比
  • 并且让整体的一个渲染的过程是能够中断的
  • 它就可以进行一个任务的调度,提升 cpu 性能
    • 因为 js 是一个单线程的语言, 如果我们执行更新占用了非常长的时间
    • 比如,浏览器执行一些动画的渲染中间,被进程占用执行其他操作, 时间被拉长,动画就变得比较卡顿
    • 或者是我们在进行一些input的输入的时候,响应会比较的卡,因为这个时候 js 正在运行react的更新
  • 在这种时候,React 让我们能够去区分一些优先级比较高和比较低的任务
  • 在进行一个 React更新的过程当中,它优先执行优先级高的任务
  • 在等浏览器把这些优先级高的任务,执行完之后,它有空余的时间的时候,再来执行优先级较低的任务

2 ) 实例演示

// ConcurrentMode 以前叫做 unstable_ConcurrentMode // 这个就是上面说的 过渡 API
import React, { unstable_ConcurrentMode as ConcurrentMode } from 'react'; // react 16.6 版本
// import React, { ConcurrentMode } from 'react'; // react 16.7 版本
// 这个会强制执行某个更新操作时, 使用优先级最高方式进行更新
import { flushSync } from 'react-dom;
import './index.css'

class Parent extends React.Component {
  state = {
    async: true,
    num: 1,
    length: 2000,
  }

  componentDidMount() {
    this.interval = setInterval(() => {
      this.updateNum()
    }, 200)
  }

  componentWillUnmount() {
    // 别忘了清除interval
    if (this.interval) {
      clearInterval(this.interval)
    }
  }

  updateNum() {
    const newNum = this.state.num === 3 ? 0 : this.state.num + 1
    if (this.state.async) {
      this.setState({
        num: newNum,
      })
    } else {
      flushSync(() => {
        this.setState({
          num: newNum,
        })
      })
    }
  }

  render() {
    const children = []

    const { length, num, async } = this.state

    for (let i = 0; i < length; i++) {
      children.push(
        <div className="item" key={i}>
          {num}
        </div>,
      )
    }

    return (
      <div className="main">
        async:{' '}
        <input
          type="checkbox"
          checked={async}
          onChange={() => flushSync(() => this.setState({ async: !async }))}
        />
        <div className="wrapper">{children}</div>
      </div>
    )
  }
}

export default () => (
  <ConcurrentMode>
    <Parent />
  </ConcurrentMode>
)
  • 上面 unstable_ConcurrentMode 是 ConcurrentMode 的过渡版本
    • 在后续16.7 实验版本的源码中是这样判断的
       var enableStableConcurrentModeAPIS = true // 注意这里是 true
       // ... 中间省略很多代码
       if (enableStableConcurrentModeAPIS) {
          React.ConcurrentMode  = REACT_CONCURRENT_MODE_TYPE;
          React.Profiler = REACT_POFILER_TYPE;
       } else {
          React.unstable_ConcurrentMode  = REACT_CONCURRENT_MODE_TYPE;
          React.unstable_Profiler = REACT_POFILER_TYPE;
       }
      
  • 关于上面的 flashSync 这个API
    • 它会强制我们在执行某一个更新操作的时候,使用优先级最高的方式去进行一个更新
    • 在 ConcurrentMode 有一个特性
      • 我们在一个子树当中渲染了 ConcurrentMode 之后
      • 它下面的所有的节点产生的更新,就是一个低优先级的更新
      • 上面的示例,把整体渲染都放在这个 ConcurrentMode 下面, 所以这个组件它产生的所有更新
      • 就是我们通过 setState 这种方式去创建的这种更新, 它都是处于一个低优先级的
  • 上面的示例,展示了低优先级和高优先级它的一个区别
    • 使用 flashSync 来提高整体的一个优先级
  • 上面示例程序渲染了有2千个节点
    • 每个节点里面的数字是一直在变的,在这个过程当中
    • 我们又给浏览器增加了一个持续性的动画,就是让整体的一个区域左右的移动
    • 动画的优先级明显是较高的
  • 主要关注 updateNum 这个函数的 if else 判断
  • 就是我们通过一个 checkbox 来切换 async 的情况
    • 当结果为 false 时,调用 flashSync,因为它是一个优先级较高的任务,强制立马更新掉
    • 效果就是: 数字变化特别快,但是动画运动就特别卡
  • 这就是 异步模式 (async mode) 和 同步模式(sync mode) 的一个本质的区别
    • 在 async mode 下面会区分优先级,让整体的动画能够看起来更流畅一点
    • 在 sync mode 下面,它没有一个优先级的区别,所以它们都是一起进行的
      • 在进行更新的时候,导致我们整个动画也会变得一卡一卡的感觉

3 )源码探究

在 React.js 中, 看一下 ConcurrentMode 的源码是什么

import {
  REACT_CONCURRENT_MODE_TYPE,
  REACT_FRAGMENT_TYPE,
  REACT_PROFILER_TYPE,
  REACT_STRICT_MODE_TYPE,
  REACT_SUSPENSE_TYPE,
} from 'shared/ReactSymbols';
// ... 省略其他
// 最后
if (enableStableConcurrentModeAPIs) {
  React.ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
  React.Profiler = REACT_PROFILER_TYPE;
} else {
  React.unstable_ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
  React.unstable_Profiler = REACT_PROFILER_TYPE;
}
  • 在这里面 ConcurrentMode 它等于的是一个常量,它是一个 REACT_CONCURRENT_MODE_TYPE
  • 是从 shared/ReactSymbols 文件中导入的一个类型,本质是一个 Symbol
    export const REACT_CONCURRENT_MODE_TYPE = hasSymbol
      ? Symbol.for('react.concurrent_mode')
      : 0xeacf;
    
  • 我们自己写组件的时候,我们都知道里面会有特别多的一些东西,我们要写一些 state
    • 比如,业务逻辑 或者在 function component 里面至少渲染一些东西
    • 但是我们这个组件它就是一个简单的 Symbol,没有任何其他的东西
  • 目前,先不去探究它如何来承载其他组件的
10X Genomics数据实战:手把手教你用Seurat处理单细胞PBMC数据(附完整代码) 本文详细介绍了如何使用Seurat处理10X Genomics的单细胞PBMC数据,从数据获取、质控到降维分析和细胞分群的全流程。通过实战代码演示,帮助研究者掌握单细胞RNA测序数据分析的核心技术,提升对细胞异质性的理解。 阅读详情

相关推荐

Ubuntu下OpenOCD+GDB的安装、编译及使用

目标开发板(芯片):stm32mp157aaa 仿真器:ST-Link 操作系统:Ubuntu 18.04 调试软件:OpenOCD OpenOCD的安装 首先下载OpenOCD有多种方式,可以GitHub上下载,目录下打开终端,输入 git clone git://git.code.sf.net/p/openocd/code openocd 下载完整的OpenOCD的文件夹。进入到OpenOCD的目录下,开始安装。 接着,OpenOCD适用于微处理器的debug和烧写,需要下载相关库 sud

蓝冰露的博客 9525

React框架的Concurrent Mode

主要总结React框架的Concurrent Mode的时间切片、可中断渲染、优先级调度等内容。

热爱前端的大宝同学。 1039

基于灰度信息的图像配准方法

图像配准方法分为三种:基于灰度信息方法、基于变换域方法和基于特征方法。基于灰度信息方法是直接根据图像或图像块灰度信息进行像素上的对齐,该方法主要思想是直接最小化图像信息差异。然而,图像信息差异的判断准则衍生出不同的配准方法。常见的基于灰度信息的图像配准方法包括互相关法、互信息法和误差平方和法。本节将分别对互相关法、互信息法和误差平方和算法展开介绍,并通过MATLAB进行演示。基于灰度的图像方法容易实现,但同样存在不足。该方法对成像条件(光照,遮挡)、图像形变旋转以及噪声极其敏感,同时具有较高的计算复杂度。

weixin_42068054的博客 3778

【React】React18新特性 - Concurrent Mode(CM)

【React】React18新特性 - Concurrent Mode(CM)

owo_ovo的博客 1052

手把手教你用AirSim和Unreal4在Ubuntu上创建自定义无人机仿真场景

本指南详细介绍了如何在Ubuntu系统上使用AirSim和Unreal Engine 4搭建高精度无人机仿真环境。从硬件配置、驱动安装到Unreal Engine编译和AirSim集成,手把手教你创建自定义场景,适用于算法验证和开发测试。

y7z8a的博客 258

Vim 入门到够用:Linux 文本编辑器的三种模式、常用操作与实战技巧

i 进入编辑模式Esc 退出编辑模式回到命令模式: 从命令模式进入底行模式编辑,不一定非得“打开就直接打字”。一旦你接受了“模式”这件事,后面很多操作都会顺起来。学 Vim,不要追求一次学全,先把“命令模式—编辑模式—底行模式”这条主线练熟。只要这条主线通了,后面的复制、删除、搜索、替换,都是顺手补上去的能力。

Web安全工具库 804

React渲染机制及相关优化方案

文章主要简单记录react中的渲染机制以及相关的优化方案,内容包括如下: (1)react渲染步骤、concurrent机制以及产生作用的机会;(2)简单模拟实现 concurrent mode;(3)基于作业调度优先级的思路进行项目优化的两个hooks;(4)案例演示

weixin_53068161的博客 4031

UVM环境复位--stop_sequences()

在UVM验证环境中, stop_sequences是一个用于强制终止所有正在运行的 Sequence 的方法,通常用于动态控制激励生成流程。1.通过uvm_config_db传递事件和严格的同步机制,此方案符适用于复杂复位场景和动态测试控制。组件耦合:Driver 和 Sequence 不再直接依赖env,通过标准接口通信。竞争条件:确保 Driver 完成清理后再终止 Sequence。代码健壮性:使用非阻塞操作和事件监听,避免死锁。

qq_42779035的博客 3016

React 18 并发模式:提升应用性能和用户体验

React 18 的并发模式是一个非常有用的功能,它可以提高应用程序的性能和用户体验,使得应用程序可以更加高效地响应用户的操作,并保持流畅的体验。对于开发者们来说,在使用并发模式时需要注意一些细节和问题,确保应用程序能够正常运行。但是,随着并发模式的不断改进和普及,相信在未来,React 的并发模式将会成为 React 应用程序开发中的标配。

uijj556的博客 2353

为什么我的Win11家庭版找不到BitLocker?教你两种强制关闭加密的隐藏方法

本文解释了Win11家庭版为何缺少BitLocker功能,并提供了两种强制关闭加密的隐藏方法。通过注册表修改和PowerShell命令,用户可以调出隐藏的加密控制面板或直接操控加密引擎,解决家庭版设备加密的管理难题。

weixin_42535703的博客 1782

白话机器学习算法理论+实战番外篇之Xgboost

1. 写在前面 如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,在这简单的先捋一捋, 常见的机器学习算法: 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支持向量机,集成算法Adaboost等 无监督算法:聚类,降维,关联规则, PageRank等 我前面已经尝试用最白话的语言完成了一个白话机器学习算法理论+实战系列,这个系列已经基本包含了上面这些算...

Miracle8070 1万+

React16源码: React中的updateMode的源码实现

`Mode` 组件是 react提供给我们的原生组件, 一共有两个: `ConcurrentMode` 和 `StrictMode`, 对于这两个 Mode 的更新过程最终调用的都是 `updateMode` 的方法, 它们执行的过程非常的简单,就是通过 `reconcileChildren` 去创建children就可以了

Wang的专栏 1056

华为OD技术面真题 - 数据库Redis - 1

汇总华为OD技术面真题Redis方面高频真题,提供详细解答。

qq_45776114的博客 935

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

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

Wang的专栏 1647

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

React16源码: React中的不同的expirationTime的源码实现

在React中不仅仅有异步任务,大部分情况下都是同步的任务,所以会有不同 expirationTime 的存在

Wang的专栏 1493

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

React16源码: memo, Fragment, StrictMode, cloneElement, createFactory源码实现

关于 memo, Fragment, StrictMode, cloneElement, createFactory 的源码实现

Wang的专栏 921

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

React16源码: React中的renderRoot的错误处理的源码实现

经过以上的处理,在调用了所有 exception 之后,最后 立马调用了。这就说明这个节点报错了,这个节点已经完成了,它不会再继续去渲染它的子节点了。它走的就是 unwindWork 的流程了, 这个后续来看。因为这个节点它已经出错了,再渲染它的子节点是没有任何意义。所以在这里面,如果有一个节点,出错了,就会立马对它执行。里面的 do while 循环中。这个是常规处理错误的处理器。

Wang的专栏 1596

react源码解析16.concurrent模式

Fiber为concurrent架构提供了数据层面的支持。Scheduler为concurrent实现时间片调度提供了保障。Lane模型为concurrent提供了更新的策略上层实现了batchedUpdates和Suspense。

js_2028的博客 200

前端进阶之React原理、源码解读-上篇

不折腾的前端,和咸鱼有什么区别!

halations的博客 1003

前端跳槽必备源码剖析:核心揭秘React 18

在开始源码剖析之前,我们先来简要回顾一下React 18的主要特性。React 18带来了Suspense、Concurrent Mode、Start Transition等新特性,为开发者们提供了更强大的性能优化能力和更灵活的组件加载方式。同时,React 18还对原有的API进行了改进和优化,使得开发体验更加流畅。通过本文的深入剖析和实战技巧分享,相信你已经对React 18的底层原理和实战应用有了更深入的了解。希望这些知识和技巧能够助你在前端领域取得更大的突破和成功!

xuxian的博客 1083

深度理解 React Suspense(附源码解析)

本文介绍与 Suspense 在三种情景下使用方法,并结合源码进行相应解析。欢迎关注个人博客。 Code Spliting 在 16.6 版本之前,code-spliting 通常是由第三方库来完成的,比如 react-loadble(核心思路为: 高阶组件 + webpack dynamic import), 在 16.6 版本中提供...

weixin_34250434的博客 302

React 16.7 Fiber源码解读 (一)之数据结构

React Fiber提出有一段时间了,关于它的文章汗牛充栋,从React 16.0 到React 16.4 (项目使用版本) 再到最新的 React 16.7,尽管大致框架没变,但是实现细节一直在变,在不同时间点发布的React Fiber源码间切换难免会有错乱。因此决定对Fiber运行框架基于最新React 16.7做一个大致的梳理

辰辰沉沉大辰沉 3938

【React】1040- 六个问题让你更懂 React Fiber

大家好,我是零一,很多人都摸不透React,看不懂源码,甚至不想看源码(确实很难看懂啊!),"霸王硬上弓" 肯定是不行呀,不如从React的整体架构或者说从最核心的Fibe...

pingan8787 897

深度理解 React Suspense

本文介绍与 Suspense 在三种情景下使用方法,并结合源码进行相应解析。欢迎关注个人博客。 Code Spliting 在 16.6 版本之前,code-spliting 通常是由第三方库来完成的,比如 react-loadble(核心思路为: 高阶组件 + webpack dynamic import), 在 16.6 版本中提供了 Suspense 和 lazy 这两个钩子, 因此在之后...

weixin_33868027的博客 442

React 源码讲解第 4 节- Fiber 对象

本小节介绍 Fiber 对象的含义、类型以及具体包含哪些属性。

杏子 822

【笔记-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 1168
上一篇: React16源码: context用法与createContext源码实现
下一篇: React16源码: Suspense与lazy源码实现
Wang's Blog
博客等级 码龄12年 7438粉丝 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、付费专栏及课程。

余额充值