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

万字长文+图文并茂+全面解析 React 源码 - render 篇 今天想了比较久的时间,准备开启这一系列的文章,旨在对 React 系列的源码进行深度解析,其中包含但不限于 react、react-dom、react-router... 等一系列优秀的 React 系列框架,最后再一一实现这些框架的简易版本。 本篇文章将会是对 react 和 react-dom 渲染过程源码的深度解析,我们将从官方 API 以及一些简易 Demo 来进入 react 的内部世界... 阅读详情

HostRoot 的更新


1 )概述

  • HostRoot 是一个比较特殊的节点, 因为在一个react应用当中
  • 它只会有一个 HostRoot, 它对应的 Fiber 对象是我们的 RootFiber 对象
  • 重点在于它的更新过程

2 )源码

定位到 packages/react-reconciler/src/ReactFiberBeginWork.js#L612

// 这个函数的重点在: update 来自哪里, 里面是什么内容
// 最终通过 processUpdateQueue 得到了 element 里面的内容,之后以此作为children来调和
function updateHostRoot(current, workInProgress, renderExpirationTime) {
  // 跳过 context 相关
  pushHostRootContext(workInProgress);
  const updateQueue = workInProgress.updateQueue;
  invariant(
    updateQueue !== null,
    'If the root does not have an updateQueue, we should have already ' +
      'bailed out. This error is likely caused by a bug in React. Please ' +
      'file an issue.',
  );
  // 获取一系列数据
  const nextProps = workInProgress.pendingProps;
  const prevState = workInProgress.memoizedState;
  // 对于 HostRoot 一开始是没有 state,也就是 `prevState.element`, 在第一次渲染的时候,prevState 是 null,在ReactDOM.render中创建了一个update
  // 经过 processUpdateQueue 这次更新后,它会拿到一个 {element} 对象作为 state
  const prevChildren = prevState !== null ? prevState.element : null;
  // 得到创建的update传递的element
  processUpdateQueue(
    workInProgress,
    updateQueue,
    nextProps,
    null,
    renderExpirationTime,
  );
  const nextState = workInProgress.memoizedState;
  // Caution: React DevTools currently depends on this property
  // being called "element".
  const nextChildren = nextState.element;
  if (nextChildren === prevChildren) {
    // If the state is the same as before, that's a bailout because we had
    // no work that expires at this time.
    resetHydrationState(); // 服务端渲染,复用dom节点相关内容
    // 跳出更新过程,不需要更新
    // 对 RootFiber来说,大部分情况下,只在 ReactDOM.render 的时候有更新,其他时候都不需要更新
    // 一般都是在App内更新,不会在RootFiber节点创建更新
    return bailoutOnAlreadyFinishedWork(
      current,
      workInProgress,
      renderExpirationTime,
    );
  }
  const root: FiberRoot = workInProgress.stateNode;
  // 跳过 hydrate 相关
  if (
    (current === null || current.child === null) &&
    root.hydrate &&
    enterHydrationState(workInProgress)
  ) {
    // If we don't have any current children this might be the first pass.
    // We always try to hydrate. If this isn't a hydration pass there won't
    // be any children to hydrate which is effectively the same thing as
    // not hydrating.

    // This is a bit of a hack. We track the host root as a placement to
    // know that we're currently in a mounting state. That way isMounted
    // works as expected. We must reset this before committing.
    // TODO: Delete this when we delete isMounted and findDOMNode.
    workInProgress.effectTag |= Placement;

    // Ensure that children mount into this root without tracking
    // side-effects. This ensures that we don't store Placement effects on
    // nodes that will be hydrated.
    // 在 current === null || current.child === null 这种情况下,都是第一次渲染
    workInProgress.child = mountChildFibers(
      workInProgress,
      null,
      nextChildren,
      renderExpirationTime,
    );
  } else {
    // Otherwise reset hydration state in case we aborted and resumed another
    // root.
    // 不是第一次渲染
    reconcileChildren(
      current,
      workInProgress,
      nextChildren,
      renderExpirationTime,
    );
    resetHydrationState();
  }
  return workInProgress.child;
}
  • HostRoot 创建更新的过程就是在 ReactFiberReconciler.js 中的调用 ReactDOM.render 的过程
  • 定位到 scheduleRootUpdate 位置在 packages/react-reconciler/src/ReactFiberReconciler.js#L110
    function scheduleRootUpdate(
      current: Fiber,
      element: ReactNodeList,
      expirationTime: ExpirationTime,
      callback: ?Function,
    ) {
      // ... 省略
      const update = createUpdate(expirationTime);
      update.payload = {element};
      // ... 省略
      return expirationTime;
    }
    
    • 它这里创建一个 update, 并挂在 update.payload 是 {element}
    • 这个 element 就是传给 ReactDOM.render 的第一个参数
    • 这个 update 对象没有后续指定类型
    • 这和调用 setState 在组件内创建更新效果是类似的
    • 所以,update.payload 就相当于 state
    • 对于 HostRoot 来说, 它的state只有一个属性,就是element
    • 就是 ReactDOM.render 的第一个参数
react-native源码分析系列四 ReactRootView 这篇文章分析一下ReactRootView类 主要focus在touch的处理上。 ReactRootView.java public class ReactRootView extends SizeMonitoringFrameLayout implements RootView       /////////***** RootView.java public interface 阅读详情

相关推荐

Spatio-Temporal Graph Convolutional Networks: A Deep Learning Framework for Traffic Forecasting 论文笔记

Spatio-Temporal Graph Convolutional Networks: A Deep Learning Framework for Traffic Forecasting 论文笔记-----GCN在交通领域的应用(二) 一、论文翻译: 1、摘要: 及时准确地交通预测对于城市交通控制和指导具有至关重要的意义。由于交通流量的非线性和复杂性,传统的方法不能满足中长期预测任务的需求,并且往往会忽略时空数据的时间和空间依赖特性。在这篇论文中,为了处理在交通领域的时间序列预测问题...

cy_believ的博客 1918

React源码解析18(3)------ beginWork的工作流程【mount】

OK,经过上一篇文章。生成了FilberRootNode和HostRootFilber。并且二者之间的对应关系也已经确定。//第一节实现的jsx方法})});所以我们现在要实现ReactDOM.createRoot中返回的render方法。

weixin_46726346的博客 1456

从 Pandas 到 Polars 十八:数据科学 2025,对未来几年内数据科学领域发展的预测或展望

Rust 在数据科学家中的普及将受到 Polars 的推动,用户会发现从使用 Python 切换到 Rust API 的门槛相对较低——比从 Pandas 切换到 C 的门槛要低得多!在数据科学蓬勃发展的十年里,我所在领域的日常工作主要由像 Python 这样的动态语言或像 R 和 Julia 这样使用即时编译的语言主导。尽管这两个库的功能有很多重叠,但有些人会想要一个像 DuckDB 这样的工具,它拥有更多关系型数据库的陷阱,而有些人则不会。然而,一位受访者正确地指出,基于GPU的库(如cuDF)更快。

sosogod的博客 2467

向量数据库选型实战:从场景出发的11款主流方案深度解析

本文深度解析11款主流向量数据库的选型实战,从专业向量数据库如Milvus、Weaviate到传统数据库扩展如PgVector、Redis Stack,覆盖不同应用场景需求。通过性能实测数据和成本考量,帮助开发者根据数据规模、查询性能等维度选择最适合的向量数据库方案,提升AI应用效率。

weixin_30315723的博客 585

别再手动拆解字节了!用博图这个功能指令,5分钟搞定ARRAY转BOOL数组

本文详细介绍了西门子博图中`ARRAY_TO_BOOL`功能指令的高效应用,帮助工程师快速实现ARRAY到BOOL数组的转换。通过实战案例和参数配置指南,展示了如何5分钟内完成传统方法需半小时的任务,大幅提升PLC编程效率,特别适用于通信报文解析和设备状态监控。

weixin_42653691的博客 265

【OpenAirInterface知识-3】OAI端到端部署之5G基站部署

在上一篇文章中已经完成了5G核心网的部署,本篇文章将介绍OAI 5G基站的部署过程。

起名字难上难的博客 3423

How React Works (一)首次渲染

How React Works (一)首次渲染 一、前言   本文将会通过一个简单的例子,结合React源码(v 16.4.2)来说明 React 是如何工作的,并且帮助读者理解 ReactElement、Fiber 之间的关系,以及 Fiber 在各个流程的作用。看完这篇文章有助于帮助你更加容易地读懂 React 源码。初期计划有以下几篇文章: 首次渲染 事件机制 更新流程 调度机制 二、核...

weixin_30915275的博客 184

C# Socket网络通信UDP(关键字:Socket)

简单Socket-Udp通信 在本文中涉及到通信,仅做简单的通信(服务端接受消息,由客户端发出消息) 如有需要,根据需求可直接copy使用 关键字Socket 需要引用命名空间: using System.Net; using System.Net.Sockets; 服务端: using System; using System.Net; using System.Net.Sockets; u...

MelanceXin的博客 3889

React的调和过程(Reconcilliation)

Reconciliation 是实现UI更新的一个过程。目的就是在用户无感知的情况下降数据的更新体现到UI上。 触发调和的方式 ReactDom.render() 函数 和 ReactNativeRender.render()函数 setState()函数 forceUpdate()函数的调用 comopnentWillMount 和 componentWillReceiveProp 中直接修改了state(地址) hooks中的useReducer 和 useState 返回的钩子函数 virtual

qq_44786519的博客 1230

智能车图像处理3-入门级分析2 ---直道冲刺

PS :入门级文章适合新手,如果已经有基础可以去看进阶篇文章。

taiyuezyh的博客 4324

使用Captum库对CIFAR数据集进行模型可解释性分析

为了训练模型,我们需要指定损失函数和优化技术。损失函数用于衡量模型的性能,在训练过程中,我们通过调整模型参数来最小化损失。本教程使用。

2501_90323865的博客 178

React 16.12.0 源码解读(二)之任务调度

React任务调度部分的源码梳理和解读。

Babyfaceqian的博客 257

Android 13 灭屏音乐播放问题解决与优化建议

通过在中增加对音乐播放状态的检测,我们成功解决了客户应用在灭屏状态下音乐播放被中断的问题。

m0_60898338的博客 1157

react 启动到创建RootFiber源码解析

react三种启动模式 legacy // LegacyRoot ReactDOM.render(<App />, document.getElementById('root'), dom => {}); // 支持callback回调, 参数是一个dom对象 Blocking模式 仅提供了 concurrent 模式的小部分功能, 作为迁移到 concurrent 模式的第一个步骤. // BolckingRoot // 1. 创建ReactDOMRoot对象 const r

weixin_43294560的博客 1038

STM32F407中文手册

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

pscad IEEE标准系统搭建说明

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

react源码学习-实习篇-状态更新

实现篇-状态更新 状态更新的流程-几个关键节点 先了解几个关键函数的调用,看看常见触发状态更新的方法是如何工作的。 render阶段的开始 之前就了解归,render阶段开始于performSyncWorkOnRoot/performConcurrentWorkOnRoot,他们会执行对应的performUnitOfWork方法。 commit阶段的开始 commit阶段开始于commitRoot方法的调用,rootFiber作为传参。 render阶段完成后会进入commit阶段。那么从触发状态更新,到r

lin_fightin的博客 1755

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

react 对象渲染_小前端读源码 React16.7.0(渲染总结篇)

读前须知之前写了五篇关于React的渲染过程的阅读流程,发现其实很多事情都写得比较青涩难懂,当然也可能是我的写作水平问题,中间其实也没有去说一些生命周期的事情。所以将会用一篇比较长的总结文章去说明React16.7.0的代码流程。个人建议不要单纯的看,结合源码一起看,会比较容易了解到里面的原理和意思。之前的几篇文章链接:小前端读源码 - React16.7.0(一)—— ReactEl...

weixin_39521009的博客 230

SAP B1中文培訓教材_SDK

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

react源码-debuger解析- createRoot阶段1

看懂这个之后https://react.iamkasong.com开始debugger源码 CreateRoot ReactDOM.createRoot(document.getElementById('')) craeteRoot主要调用了createContainer创建rootFiber和FiberRoot,并且将它们联系起来。 createContainer```调用了```createFiberRoot const root: FiberRoot = new FiberRootNode(...)

lin_fightin的博客 2256

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万+

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

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

Wang的专栏 8836

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

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

Wang的专栏 6714

React 实现 2D 画板功能

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

Wang的专栏 4325

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

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

Wang的专栏 2803

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

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

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

Wang的专栏 2796

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

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

Wang的专栏 2397

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
上一篇: React16源码: React中的IndeterminateComponent的源码实现
下一篇: React16源码: React中的HostComponent & HostText的源码实现
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、付费专栏及课程。

余额充值