React16源码: React中的setState和forceUpdate源码实现

前端React篇之哪些方法会触发 React 重新渲染?重新渲染 render 会做些什么? 在React中,组件的重新渲染可以通过setState()、forceUpdate()、props或state的改变、父组件的重新渲染以及context的改变来触发。当组件重新渲染时,React会执行render方法,生成新的虚拟DOM树 阅读详情

setState 和 forceUpdate


1 ) 概述

  • 通过 class component 内部的 setState,以及 forceUpdate 去更新一个组件的过程
  • 在react的应用当中,我们只有 ReactDOM.render setState,以及 forceUpdate
  • 这几种种方式去更新react的应用是合理的,其他没有什么特别常用的方式去更新了
  • 而且react官方推荐的也是用这些。forceUpdate 其实本身也不是特别推荐的
  • 因为有比较特殊的作用,以及比较特殊的使用场合, 也算是一个比较有用的API
  • 在React16.7之后发布的Hooks, Hooks里面我们通过
  • useState 返回过来的一个方法,也可以去更新一个组件的状态
    • 这块看不到源码,只能看到打包之后的代码
    • 它的设置比较特殊,这块先跳过
  • setState,以及 forceUpdate的核心,首先是他们是给节点 Fiber 去创建更新的
  • 对于 ReactDOM.render 来说,它创建的 update 是放在root上面
  • 它是一个整体的渲染,因为执行 ReactDOM.render 的时候
  • 整个应用都没有任何的产生,任何的节点都没有生成,是一个初始的渲染
  • 所以 setState 和 forceUpdate 是针对某一个 class component 来说的
    • 这个 class component 的状态来进行更新
    • 把新的状态计算并渲染出来
  • setState 和 forceUpdate 两者更新的类型不同
    • 它们上面有 UpdateState, ForceUpdate 两种不同的 tag
    • 这个tag就对应的它们是更新的类型不同

2 )源码

  • 先跳过 组件如何去渲染

    • 也就是我们的 class component,什么时候会被实例化
    • 这个涉及到后面的更新的流程
  • 我们的component的BaseClass在初始化的时候会拿到一个update的这个对象

  • 这个对象来自于哪个地方

  • 源码: https://github.com/facebook/react/blob/v16.6.0/packages/react-reconciler/src/ReactFiberClassComponent.js

  • 这个文件中,有涉及很多 class 相关的代码

    const classComponentUpdater = {
      isMounted,
      enqueueSetState(inst, payload, callback) {
        const fiber = ReactInstanceMap.get(inst); // inst 是调用 this.setState 时的 this,在react渲染的时候会通过 `ReactInstanceMap` 做映射和获取 Fiber对象
        const currentTime = requestCurrentTime();
        const expirationTime = computeExpirationForFiber(currentTime, fiber);
    
        const update = createUpdate(expirationTime);
        update.payload = payload; // 这里 payload 是 setState时传入的对象
        if (callback !== undefined && callback !== null) {
          if (__DEV__) {
            warnOnInvalidCallback(callback, 'setState');
          }
          update.callback = callback; // 挂载 callback
        }
    
        enqueueUpdate(fiber, update); // 把fiber对象的updateQueue进行初始化或更新
        scheduleWork(fiber, expirationTime); // 进行调度处理
      },
      enqueueReplaceState(inst, payload, callback) {
        const fiber = ReactInstanceMap.get(inst);
        const currentTime = requestCurrentTime();
        const expirationTime = computeExpirationForFiber(currentTime, fiber);
    
        const update = createUpdate(expirationTime);
        update.tag = ReplaceState;
        update.payload = payload;
    
        if (callback !== undefined && callback !== null) {
          if (__DEV__) {
            warnOnInvalidCallback(callback, 'replaceState');
          }
          update.callback = callback;
        }
    
        enqueueUpdate(fiber, update);
        scheduleWork(fiber, expirationTime);
      },
      enqueueForceUpdate(inst, callback) {
        const fiber = ReactInstanceMap.get(inst);
        const currentTime = requestCurrentTime();
        const expirationTime = computeExpirationForFiber(currentTime, fiber);
    
        const update = createUpdate(expirationTime);
        update.tag = ForceUpdate;
    
        if (callback !== undefined && callback !== null) {
          if (__DEV__) {
            warnOnInvalidCallback(callback, 'forceUpdate');
          }
          update.callback = callback;
        }
    
        enqueueUpdate(fiber, update);
        scheduleWork(fiber, expirationTime);
      },
    };
    
    • 这里面主要关注, enqueueSetState 和 enqueueForceUpdate 这两个enqueue 方法几乎一样,两者区别 看 update.tag
    • 看了上面的源码,发现 和 react-reconciler/src/ReactFiberReconciler.js 中的 updateContainer 很像
      • 内部调用 updateContainerAtExpirationTime 接着调用 scheduleRootUpdate 在这里面都基本相似
  • 所以,在React中创建更新的过程都是差不多的,创建完更新后,进入队列,就会进行整个应用的更新

  • React 是一个非常纯粹的框架,所有的核心都是服务应用的整体更新的, 就是 scheduleWork 函数进入之后的整体更新流程

  • 这块在React整体的代码量中占据非常大的比例

【react全家桶学习】react的 (新/旧) 生命周期(重点) 相对比vue的生命周期,react显得复杂的多,光从名称上就比vue长,所以做好准备,不要放弃,坚持就是胜利、 阅读详情

相关推荐

React组件类型解析:Component、PureComponent与函数组件

React组件是构建用户界面的核心单元,主要分为类组件和函数组件两种范式。类组件通过继承React.Component或React.PureComponent实现,提供了完整的生命周期管理和状态控制能力,其中PureComponent通过浅比较props和state自动优化渲染性能。函数组件则是更轻量的选择,配合Hooks可以实现与类组件相同的功能,且代码更简洁。在React Fiber架构下,函数组件通过闭包管理状态,避免了类组件中this绑定的问题。对于性能敏感的场景,PureComponent的浅比较

weixin_34197488的博客 363

React-forceUpdate()

默认情况下,当组件的state或props改变时,组件将重新渲染。如果你的render()方法依赖于一些其他的数据,你可以告诉React组件需要通过调用forceUpdate()重新渲染。 调用forceUpdate()会导致组件跳过shouldComponentUpdate(),直接调用render()。这将触发组件的正常生命周期方法,包括每个子组件的shouldComponentU...

Leon的博客 4万+

use-force-update:React Hook强制您的功能组件进行更新

useForceUpdate useForceUpdate是一个React Hook,可强制您的功能组件重新呈现。 useForceUpdate本身并没有用途。 这是一个很小的软件包,旨在集成到更大的钩子中,使仍依赖于this.forceUpdate()所有类功能都过时。 安装 npm install use-force-update或 yarn add use-force-update 利用 import React from ' react ' ; import useForceUpdate from ' use-force-update ' ; export default func

React组件生命周期过程说明

实例化 首次实例化 getDefaultProps getInitialState componentWillMount render componentDidMount 实例化完成后的更新 getInitialState componentWillMount render componentDidMount 存在期 组件已存在时的状态改变 comp...

weixin_30756499的博客 372

React Hook 强制您的功能组件更新。

useForceUpdate useForceUpdate 是一个 React Hook,它强制您的函数组件重新渲染。 useForceUpdate 本身没有任何用途。 它是一个小包,旨在集成到更大的钩子中,使仍然依赖 this.forceUpdate() 的任何类功能过时。 安装 npm install use-force-update 或 yarn add use-force-update 使用 import React from 'react'; 从“use-force-update”导入 useForceUpdate; 导出默认函数 MyButton() { const forceUpdate = useForceUpdate(); const handleClick = React.useCallback(() => { alert('我现在要重新渲染。'); forceUpdate(); }, [forceUpdate]); 返回(重新渲染); };

【论文阅读】LIME:Low-light Image Enhancement via Illumination Map Estimation(笔记最全篇)

文章目录AbstractIntroductionContributionMethodSpeed-up Method(1):ALM子问题 T子问题 G子问题 Z和μ\muμSpeed-up Method(2):权重变量实验conclusion 今天要整理的一篇论文是使用传统的方法解决低照度的问题,Guo等人于2016年发表在IEEE上,论文《LIME:Low-light Image Enhance...

florrie 2万+

React总结

React是一个用于构建用户界面的 JavaScript 库 生命周期: React 生命周期分为三种状态 1. 初始化 2.更新 3.销毁 componentWillMount() 组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state。 在渲染前调用,在客户端也在服务端。 render() react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。 compon..

lsylhx123的博客 446

小白快速上手 labelimg:新手图像标注详解教程

本教程主要帮助没有使用过labelimg的小白上手该软件,快速学会基本操作和打标签,为数据集准备打下基础。

小白一枚~ 2万+

React源码分析1-jsx转换及React.createElement

本章讲述了 jsx 在 react17 之前和之后的不同的转换,实际上 react17 之后 babel 的对 jsx 的转换就是比之前多了一步的动作:另外讲述了和的内部实现是怎样的。通过 babel及,将 jsx 转换为了浏览器能够识别的原生 js 语法,为 react 后续对状态改变、事件响应以及页面更新等奠定了基础。后面的章节中,将探究 react 是如何一步步将状态等信息渲染为真实页面的。

It_kc的博客 473

手把手教你用ObjectCRX进行Caxa二次开发:从零开始的环境搭建教程

本文是一份面向零基础初学者的Caxa二次开发实战指南,重点讲解如何使用ObjectCRX框架从零开始搭建开发环境。内容涵盖Visual Studio 2015版本锁定、ObjectCRX向导集成、项目创建、典型错误解决,并最终实现一个可在Caxa中运行的HelloWorld程序,帮助开发者快速入门并避开常见陷阱。

w3x4y的博客 514

【SpringBoot 4.x 第29节】Spring Security 7 入门:先理解认证和授权!

🏆 本文收录于 《滚雪球学 Spring Boot 4.x》 专栏。本专栏面向 有一定 Java 基础,但尚未系统学习 Spring Boot 的读者,采用“滚雪球式学习法”:先跑通、再理解、再重构、再上线,带你从第一个 Hello API 开始,逐步完成一个可部署、可监控、可扩展的后端项目。

**My Coding Family** 553

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

定位到 packages/react-reconciler/src/ReactFiberScheduler.js。拿之前的一个 Fiber Tree 节点来举例。当中,它需要去找到更新对应的。如果符合条件需要重置 stack。如果符合条件就去请求工作调度。这几个方法最终都调用了。

Wang的专栏 1525

Windows2008使用-解决漏洞-CVE-2010-2730

随着硬件的升级,操作系统也逐渐进行了版本更新。目前阶段,Windows2016Server、Windows2022Server逐渐成为了以Windows系列的服务器平台系统。对于有些应用而言,由于其业务的固定,可能仍只能运行在Windows2008Server或者Windows2012Server上。有时候我们为安全需要,需要将相关的操作系统涉及的漏洞做修复。最近碰到在一个Windows2008R2 的操作系统漏洞CVE-2010-2730,一顿操作,终于找到了合适的方案,这里分享给大家。

mystonelxj的博客 2316

React16源码: Component与PureComponent源码实现

Component 就是组件, 这个概念依托于最直观的在react上的一个表现,那就是 `React.Component`,我们写的组件大都是继承于 `React.Component` 这个baseClass 而写的类

Wang的专栏 1587

OsgEarth —— 笔记6 - 开发阶段加入漫游飞行(附源码)

效果      视频地址   源码 源码下载请私信   代码      代码相关内容:           OSG —— 笔记1 - 指令调用模型           OsgEarth —— 笔记1 - 创建地球的earth文件           OsgEarth —— 笔记2 - Qt窗口加载earth地球(附源码)           OsgEarth —— 笔记3 - 为地

1896

十年芯片资深IC设计工程师面经系列(四)SDC约束

set_driving_cell:当我们的设计是模块级(Block level)的design时,我们的设计前面一般还有其他的设计,那么前面模块的输出便是我们模块的输入,5.1set_false_path:可以单独的时钟或者路径进行约束。set drive :当我们的设计是芯片级(Chip level)的顶层设计时,芯片外围电路要驱动的是负载较大的IO单元,故需要的驱动能力较强,:set_load 是指output端口的负载,设置的值会影响输出到端口的net上的电容,从而影响相应的路径延时。

weixin_47349046的博客 1774

React16源码: React中创建更新的方式及ReactDOM.render的源码实现

在过程当中,创建了一个ReactRoot同时在ReactRoot创建的过程中创建了FiberRoot在创建的过程中也会自动去初始化一个 Fiber 对象(上面暂没有涉及)然后又在这个 root 上面去创建了一个之后又创建了一个 update 这个更新的对象,然后把这个更新的对象放到我们的 root 的节点上面之后就进入了一个更新的过程, 这就是一个创建更新的过程创建完更新, 再去实际的调度整个任务的更新。

Wang的专栏 1595

Swin Transformer 类可视化(grad CAM)

完整代码 from pytorch_grad_cam import GradCAM, ScoreCAM, GradCAMPlusPlus, AblationCAM, XGradCAM, EigenCAM from pytorch_grad_cam.utils.image import show_cam_on_image from torchvision.models import resnet50 import glob from demo import parse_option from models i

G果的博客 6639

细说react源码中的合成事件

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。部分文档展示:文章篇幅有限,后面的内容就不一一展示了有需要的小伙伴,可以点下方卡片免费领取。

郊眠寺 171

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

对react setState 的理解

我们翻开react源码(version:16.3.2), 首先是 setState部分,看到这里接受两个参数partialState (局部状态,限定只有对象和函数可以作为第一个参数), callback   Component.prototype.setState = function (partialState, callback) { !(typeof partialState =...

王为仁的博客 1365

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

React源码解读之更新的创建

React的鲜活生命起源于,这个过程会为它的一生储备好很多必需品,我们顺着这个线索,一探婴儿般React应用诞生之初的悦然。更新创建的操作我们总结为以下两种场景。

weixin_59558923的博客 599

React源码学习

文章目录1. JSX2. React 核心 API2.1 Component2.2 PureComponent2.3 setState2.4 forceUpdate 1. JSX React 使用 JSX 语法描述视图 优点: 使用 JSX 编写模板简单快速。 JSX编译为 JavaScript 代码后进行了优化,执行更快。 在编译过程中就能发现错误。 React 16原理: 通过babel-loader会预编译JSX为React.createElement(…)形式, 通过React.createE

fmk1023的博客 274

react源码分析:babel如何解析jsx

不管是类组件还是函数组件,最终我们写的jsx都被babel转化成了可识别的元素,其中我们也看了,,Component等内部实现,了解到了作为他是怎么被创建的,但是远远没有完,因为我们知道我们在写React的时候,会在后面带上一个,没错我们下一章节就要去探索一下方法了。

weixin_59558923的博客 501
上一篇: React16源码: React中的不同的expirationTime的源码实现
下一篇: React16源码: React中的schedule调度整体流程
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、付费专栏及课程。

余额充值