React16源码: React中commit阶段的commitAllHostEffects的源码实现

用Multisim仿真AD630锁定放大器:从2012年电赛A题实战到避坑指南 本文详细介绍了如何使用Multisim仿真AD630锁定放大器,从2012年电赛A题实战出发,提供完整的电路搭建、参数优化及避坑指南。重点解析AD630的开关调制架构和双相位检测的工程实现,帮助读者在强噪声背景下有效提取微弱信号,提升电子设计竞赛和工程实践中的信号处理能力。 阅读详情

commitAllHostEffects


1 )概述

  • 在 react commit 阶段的 commitRoot 第二个while循环中
  • 调用了 commitAllHostEffects
  • 现在来看下,里面发生了什么

2 )源码

回到 commit 阶段的第二个循环中,在 commitRoot 函数里

定位到 packages/react-reconciler/src/ReactFiberScheduler.js#L690

看这里

nextEffect = firstEffect;
startCommitHostEffectsTimer();

// 第二个循环调用的方法是 commitAllHostEffects
// 这个就是主要是操作对于 dom 节点它需要去做的一些内容
// 比如说如果这个 dom 节点是刚刚新增的,那么要执行一个插入的操作
// 如果这个 dom 节点它需要被删除,我们要执行删除的操作
// 如果这个 dom 节点它的属性或者它 children 有更新,那么要执行一个更新的操作
while (nextEffect !== null) {
  let didError = false;
  let error;
  if (__DEV__) {
    invokeGuardedCallback(null, commitAllHostEffects, null);
    if (hasCaughtError()) {
      didError = true;
      error = clearCaughtError();
    }
  } else {
    try {
      commitAllHostEffects();
    } catch (e) {
      didError = true;
      error = e;
    }
  }
  if (didError) {
    invariant(
      nextEffect !== null,
      'Should have next effect. This error is likely caused by a bug ' +
        'in React. Please file an issue.',
    );
    captureCommitPhaseError(nextEffect, error);
    // Clean-up
    if (nextEffect !== null) {
      nextEffect = nextEffect.nextEffect;
    }
  }
}
stopCommitHostEffectsTimer();

resetAfterCommit(root.containerInfo);

注意,在执行新的循环之前,都要执行 nextEffect = firstEffect;
因为每一个 effect 对象上面可能有不同的各种 effectTag
所以它们都是要再次经历一个循环之后去判断是否要进行对应的操作的
所以每一个循环开始之前,都要重新赋值成单项链表的开头

上面是使用的地方,现在定位到 commitAllHostEffects

// https://github.com/facebook/react/blob/v16.6.3/packages/react-reconciler/src/ReactFiberScheduler.js#L392
function commitAllHostEffects() {
  while (nextEffect !== null) {
    if (__DEV__) {
      ReactCurrentFiber.setCurrentFiber(nextEffect);
    }
    recordEffect();

    const effectTag = nextEffect.effectTag;

    if (effectTag & ContentReset) {
      commitResetTextContent(nextEffect);
    }

    // 这个先跳过
    if (effectTag & Ref) {
      const current = nextEffect.alternate;
      if (current !== null) {
        commitDetachRef(current);
      }
    }

    // The following switch statement is only concerned about placement,
    // updates, and deletions. To avoid needing to add a case for every
    // possible bitmap value, we remove the secondary effects from the
    // effect tag and switch on that value.
    let primaryEffectTag = effectTag & (Placement | Update | Deletion);
    switch (primaryEffectTag) {
      case Placement: {
        commitPlacement(nextEffect);
        // Clear the "placement" from effect tag so that we know that this is inserted, before
        // any life-cycles like componentDidMount gets called.
        // TODO: findDOMNode doesn't rely on this any more but isMounted
        // does and isMounted is deprecated anyway so we should be able
        // to kill this.
        nextEffect.effectTag &= ~Placement;
        break;
      }
      // 先 Placement 后 Update
      case PlacementAndUpdate: {
        // Placement
        commitPlacement(nextEffect);
        // Clear the "placement" from effect tag so that we know that this is inserted, before
        // any life-cycles like componentDidMount gets called.
        nextEffect.effectTag &= ~Placement; // 在 处理完 Placement 之后,就去掉 Placement

        // Update
        const current = nextEffect.alternate;
        commitWork(current, nextEffect);
        break;
      }
      case Update: {
        const current = nextEffect.alternate;
        commitWork(current, nextEffect);
        break;
      }
      case Deletion: {
        commitDeletion(nextEffect);
        break;
      }
    }
    nextEffect = nextEffect.nextEffect;
  }

  if (__DEV__) {
    ReactCurrentFiber.resetCurrentFiber();
  }
}
  • 首先判断了一个叫 effectTag 是否有 ContentReset

    • 如果内部有文字的节点,文字节点需要去重置它的一个文字的内容
    • 这里调用了 commitResetTextContent, 这个方法来自于 ReactFiberCommitWork.js
      function commitResetTextContent(current: Fiber) {
        if (!supportsMutation) {
          return;
        }
        resetTextContent(current.stateNode);
      }
      
      // packages/react-dom/src/client/ReactDOMHostConfig.js#L339
      export function resetTextContent(domElement: Instance): void {
        setTextContent(domElement, '');
      }
      
      • 进入 setTextContent
        /**
         * Copyright (c) Facebook, Inc. and its affiliates.
        *
        * This source code is licensed under the MIT license found in the
        * LICENSE file in the root directory of this source tree.
        *
        * @flow
        */
        
        import {TEXT_NODE} from '../shared/HTMLNodeType';
        
        /**
         * Set the textContent property of a node. For text updates, it's faster
        * to set the `nodeValue` of the Text node directly instead of using
        * `.textContent` which will remove the existing node and create a new one.
        *
        * @param {DOMElement} node
        * @param {string} text
        * @internal
        */
        let setTextContent = function(node: Element, text: string): void {
          if (text) {
            let firstChild = node.firstChild;
            // 这里,一个first === last 代表只有一个节点,才会设置,防止有其他节点导致误删除了其他节点
            if (
              firstChild &&
              firstChild === node.lastChild &&
              firstChild.nodeType === TEXT_NODE
            ) {
              firstChild.nodeValue = text;
              return;
            }
          }
          node.textContent = text;
        };
        
        export default setTextContent;
        
        • 这个方法,就是给一个节点设置文本内容
  • 接下去,primaryEffectTag

    • 它最主要的对dom节点来说,它要执行的就是 Placement, Update, Deletion 这三种操作
    • 只有 Placement 的节点大概率是新增的节点,直接进行插入
    • 匹配 PlacementAndUpdate 可能是之前存在的节点,需要和兄弟节点进行位置交换,或需要更新
    • 只有 Update, 执行 commitWork
    • 只有 Deletion, 执行 commitDeletion
  • 接下去就是赋值 nextEffect,然后再次进入这个循环

  • 直到我们整个单链表循环完成之后,它就结束了

【Linux0.11代码分析】之 系列文章链接汇总(全) 【Linux0.11代码分析】00 之 系列文章链接汇总(全) 阅读详情

相关推荐

用Unity Wheel Collider做坦克转向?3步实现履带式载具物理效果

本文详细解析了如何利用Unity的Wheel Collider组件实现履带式载具的差速转向物理效果。通过思维转换、场景搭建和核心代码实现三步,将Wheel Collider从模拟轮式车辆转向改造为控制履带扭矩差的系统,并深入探讨了参数调试与真实感提升的方法,帮助开发者打造物理反馈扎实的坦克或特种车辆模拟。

weixin_29009971的博客 225

Fix signatures do not match the previously installed version

报错信息FAILURE: Build failed with an exception.* What went wrong: Execution failed for task ':app:installDebug'. > com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: Fai

Wang的专栏 2万+

IEEE论文投稿必看:PDF eXpress报错font not embedded的3种修复方法(附Adobe Acrobat DC操作截图)

本文针对IEEE论文投稿时PDF eXpress系统常见的“font not embedded”报错,提供了三种核心修复方案。首先,详细解析了使用Adobe Acrobat DC进行专业修复的完整操作流程与关键技巧。其次,介绍了无需付费软件的开源与免费工具链(如Ghostscript)解决方案。最后,从源头出发,指导LaTeX和Microsoft Word用户在生成PDF时正确设置以确保字体自动嵌入,帮助研究者彻底解决格式问题,确保投稿顺利。

ujm56789012的博客 517

在react中 实现 base64的图片转换成formdata格式并实现上传功能

如果不想要服务端实现处理base64格式的图片的转换,那么在浏览器端来实现,部分属于伪代码,仅作为开发参考,请勿直接拷贝使用

Wang的专栏 8836

相场断裂模型中的各向异性机制:从裂纹密度到驱动力的数值实现

断裂力学是研究材料在载荷作用下裂纹萌生与扩展规律的基础学科,其核心在于理解材料失效的能量准则与路径选择。传统方法通常预设裂纹路径,而相场断裂模型通过引入连续的相场变量,将裂纹模拟转化为一个能量最小化问题,能够自发预测裂纹的萌生、扩展与分叉,在工程失效分析中具有重要价值。当材料具有显著的方向依赖性时,如单晶、复合材料或轧制金属板,各向同性假设会失效,此时需引入各向异性机制。该机制的核心在于改造两个关键部分:一是裂纹密度函数,通过引入各向异性张量来定义不同方向上形成裂纹微结构的能量成本;二是临界能量释放率(断裂

weixin_31421613的博客 298

【100%通过率】华为OD机试真题 Python 实现【网上商城优惠活动 / 模拟商场优惠打折II】

某网上商场举办优惠活动,发布了满减、打折、无门槛3种 优惠券,分别为: 1:每满100元优惠10元,无使用数限制,如100~199元可以使用1张减10元,200~299可使用2张减20元,以此类推; 2:92折券,1次限使用1张,如100元,则优惠后为92元, 3:无门槛5元优惠券,无使用数限制,直接减5元。

MISAYAONE的博客 9373

快速解决gradle下载慢的问题的小技巧

在ionic run 或build 或clean命令的时候,如果没有下载过gradle, 需要重新下载一次,而通过CLI的方式下载很慢,即使科学上网后,下载还是存在一些问题。这里总结一下,快速的下载安装方式。 步骤 本地安装 http-server 包, 通过 $ npm i -g http-server 的方式安装到全局 在官网上下载自己的版本,目前自带的版本是 2.14.1,其他版本可能在执行过

Wang的专栏 6714

基于 Google Colab 的 mask rcnn 训练自己的数据集(以实例分割为例)

详细步骤1 数据集的制作1.1 数据标注1.2 生成数据集2 环境的搭建2.1 搭建流程2.2 注意事项(报错)3 开始训练4 可视化4.1 修改webcam.py文件4.2 进行可视化5 参考文章 1 数据集的制作 1.1 数据标注 使用 labelme=4.5.6 版本进行标注,标注文件指定到保存图片的路径下,也就是json文件和jpg文件放在同一个文件夹里 1.2 生成数据集 先手动划分训练集和测试集(包括图像和标注文件),然后分别整合它们的标注信息,参考代码:1_ships_to_coco.py

G果的博客 8002

React 实现 2D 画板功能

在移动端或者PC端我们来模拟画板的实现, 支持清除和导出功能,此处简单实现,仅作开发参考。 效果演示 主要代码演示 /* 此模块用于实现签名绘图功能 */ // 需要用到的变量定义 let clickX = new Array(); let clickY = new Array(); let clickDrag = new Array(); let paint; let point...

Wang的专栏 4325

pg lib的信息及产生pg lib的三种方法

pg lib相比basic lib会多几方面pg 信息。除了pg arc(pg pin)以外,liberty还提供电压值,以及pmk cell的power_down_function功能相关信息。1.电压值除了常见的primary pg还有secondary pg和衬底。2.pg arc后端需要去做redhawk功耗分析,需要pg liberty提供pg arc,如果没有pg arc就需要手动去写custom lib代替3.pmk cell的power_down_function。

m0_61544122的博客 596

openpi 入门教程(二)droid libero 训练、推理

OpenPI是由物理智能团队发布的机器人领域开源模型与软件平台,提供基于流扩散式(π₀)和自回归式(π₀-FAST)两类视觉-语言-动作模型。平台支持在DROID、ALOHA、UR5等多种机器人系统上部署,包含预训练检查点(1万+小时数据)和微调示例。文档详细说明了各平台部署流程:DROID需启动策略服务器并配置摄像头;ALOHA提供真实机器人任务(取吐司、叠毛巾等)的检查点和场景设置建议;UR5示例展示自定义数据转换方法。实验性验证显示π₀-FAST在LIBERO基准测试中平均得分85.5。平台强调模型适

2506_90492529的博客 1024

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

对于在 beginWork 中的 context 操作,可以看上述判断成立的条件下的代码,即便有符合跳过更新的操作,依然 需要 push 和 pop 操作。如果我们可以跳出组件的更新,也就是代表着当前这个 classComponent,它的state它的props都应该是没有任何变化的。对于子组件来说,它的所有子树所获取到的context肯定是经过子组件,和上层的父组件合并的 context 了, 也就是。所以,先 push 一个老的值进去再说, 然后到后面,如果发现这个组件它是要更新的,就调用这个。

Wang的专栏 2803

MIPI CPHY学习笔记01:TX物理层一致性测试项解析(LP信令模式)

在手机、平板、智能手表等移动设备中,MIPI C-PHY是负责图像、数据传输的核心接口,它就像设备内部的“高速数据线”,而低功耗(LP)信令模式,是这条“数据线”的“省电模式”,专门用于设备待机、低负载等场景,既要保证信号稳定,又要最大限度降低功耗。物理层一致性测试,就是给这个“省电模式”做的“全面体检”,确保不同厂商的设备能兼容互通。今天,我们就聚焦MIPI C-PHY TX(发射端)的Group 1 LP信令测试,用通俗的语言拆解8个核心测试项,看懂“省电信号”的合格标准。

一只豌豆象的博客 304

Fix babel-preset-react-native TransformError

错误环境新版本存在不兼容,在运行 react-native run-android 的时候,发生的错误分析: babel-preset-react-native version : @3.0.0 $ react-native -v :react-native-cli: 2.0.1 react-native: 0.47.1$node -v : v7.8.0 $ npm -v :4.4.4 解决方案

Wang的专栏 2800

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

React18原理: 再聊Fiber架构下的时间分片

react的任务可以被打断,其实就是基于时间分片的,人眼最高能识别的帧数不超过30帧,电影的帧数差不多是在24,浏览器的帧率一般来说是60帧,也就是每秒60个画面, 平均一个画面大概是16.5毫秒左右,浏览器正常的工作流程是运算渲染,运算,渲染运算渲染,在浏览器里面一个运算,加上一个渲染就是一帧

Wang的专栏 2796

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

在react项目中修改webpack中本地服务器架设的目录

一个产品的上线往往会有很多的问题,现在就出现一个需求,我们是在服务器下的某个目录进行发布,而不是根服务器,服务端不想为一个项目配置ip地址,而在react项目中,默认是走的根路径,现在我们就开始修改一下它。 前提说明 如果我们需要修改手动配置webpack, 那么根据现在的版本, 我们只能执行 npm run eject, 之后就可以着手修改了。 webpack中与需求相关的...

Wang的专栏 2397

VC中sqlite的使用

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

React18源码: React调度中的3种优先级类型和Lane的位运算

可以看得出来lane&-lane的结果是SyncLane,所以通过lane&-lane就能分离出最高优先级的任务。即A(cpu)>B(IO)>C(cpu).此时的需求需要将任务B从group中分离出来,先处理cpu任务A和C。在新版本的React中,还有一个新特性,就是render阶段可能被中断,在这个期间会产生一个更高优先级的任务。如上就是通过 lanes & -lanes 分离出最高优先级的任务的,我们来看一下具体的流程。也即是说lane的代表的数值越小,此次更新的优先级就越大。

Wang的专栏 2394

React18原理: 核心包结构与两大工作循环

react中的工作循环,这是它的一个最顶层的一个流程图,在这张图里面,有两个核心的大循环,第一大循环是 react-reconciler 提供的,它的核心是构建fiber树,生成任务,第二大循环是 scheduler 提供的, 它的核心是任务调度(处理任务的优先级),react的原理实际上就是两大工作循环

Wang的专栏 2356

React18原理: 生命周期中特别注意事项

生命周期就是一个组件从诞生到销毁的全过程(包含错误捕获,这里暂且不聊这个)react 在组件的生命周期中注册了一系列的钩子函数支持开发者在其中嵌入代码,并在适当的时机运行生命周期本质上就是组件中的钩子函数,主要有三个主要的钩子挂载更新卸载。

Wang的专栏 2244

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

定位到 packages/react-reconciler/src/ReactFiberBeginWork.js。整个文件 export 出去的只有 beginWork 方法。

Wang的专栏 2140

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

在更新了一个节点之后,拿到它的props.children, 要根据这个children里面的 ReactElement 来去创建子树的所有的 fiber 对象, 要根据 props.children 来生成 fiber 子树,然后判断 fiber 对象它是否是可以复用的

Wang的专栏 2133

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

各种不同类型组件的一个更新过程对应的是在执行 `performUnitOfWork` 里面 `beginWork` 阶段,它是去向下遍历一棵 fiber 树的一侧的子节点,然后遍历到叶子节点为止,以及 return 自己 child 的这种方式

Wang的专栏 2088

React18原理: 渲染与更新时的重点关注事项

react 在渲染过程中要做很多事情,所以不可能直接通过初始元素直接渲染还需要一个东西,就是虚拟节点,暂不涉及React Fiber的概念,将vDom树和Fiber 树统称为虚拟节点有了初始元素后,React 就会根据初始元素和其他可以生成虚拟节点的东西生成虚拟节点React一定是通过虚拟节点来进行渲染的对于首次挂载阶段需要了解React的渲染流程通过书写的初始元素和一些其他可以生成虚拟节点的东西来生成虚拟节点然后针对不同的节点类型去做不同的事情,最终将真实DOM挂载到页面上。

Wang的专栏 2069

21st.dev 上手教程:12000+ React 组件库怎么用,6 步从挑样式到接进 Cursor

21st.dev 收录 12000+ 个 React + Tailwind 组件、297 套整站模板与 979 套主题。本文是手把手流程版:按页面用途找组件、用复制或 shadcn CLI 落地、接入 MCP 让 Cursor 自己取代码、用整站模板开局,附 10 张真实组件截图和 4 个常见坑。

懿轩的技术小窝 232

成为全栈·Vue 管理后台篇·Naive UI 主题对齐:React 后台配色与明暗模式

本文根据 React 管理后台的蓝紫主色与浅/深色语义令牌,分析 Vue 后台如何用 CSS custom properties、Naive UI `NConfigProvider`、theme overrides、Pinia UI store 和系统媒体查询完成主题对齐。文章说明 CSS class 与 Naive UI darkTheme 必须同步,Markdown 编辑器/预览需要单独接入 resolvedTheme,并通过主题/侧栏持久化区分非敏感偏好与认证凭证。

FungLeo's Blog 215

手搓 AI Agent 02:让模型第一次“动手“——Agent Loop 与 ReAct

本系列第2篇实现Agent核心循环——ReAct模式,让模型从“被动回答”变为“主动执行”。通过LLMClient工具调用能力,构建think → act → observe闭环,首次实现模型自主调用计算器、读取结果并继续推理。代码支持安全算术、步数限制与错误隔离,升级终端REPL为可观察的智能体交互界面。每步操作清晰可见,为后续多工具、规划与协作打下基础。

快乐来自程序里 131
上一篇: React16源码: React中commit阶段的commitBeforeMutationLifecycles的源码实现
下一篇: React16源码: React中commitAllHostEffects内部的commitPlacement的源码实现
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、付费专栏及课程。

余额充值