React原理 - React New Component Lifecycle

news2025/3/10 23:10:38

目录

扩展学习资料

React New Component Lifecycle【新生命周期】

React 组件新生命周期详解

React组件老生命周期 v15.x

为什么Fiber Reconciler要有新的生命周期函数呢?

新的组件生命周期

getDerivedStateFromProps

挂载阶段

更新阶段

卸载阶段

异常捕获

新版组件升级

升级组件版本

APP.js

component.js

升级组件遍布-保留选项


扩展学习资料

名称

链接

React 组件

React.Component – React

React v16.3 组件生命周期

关于React v16.3 新生命周期 - 掘金

React 组件图

React lifecycle methods diagram

React New Component Lifecycle【新生命周期】

掌握新的组件生命周期,在老的生命周期组件中进行更新代码。

React 组件新生命周期详解

React组件老生命周期 v15.x

  1. Initialization【初始化】:state的初始化;及props是否转化为state;setup;
  2. Mounting【挂载过程】:componentWillMount()【新版删除1】->render()->componentDidMount()
  3. Updation【业务更新】:(props【父级传递的props更新;被动更新】)=>componentWillReceiveProps()【新版删除2】->shouldcomponentUpdate(){return true}-> componentWillUpdate()【新版删除3】->render()->componentDidUpdate();(states【主动调用setState更新】)=>shouldcomponentUpdate(){return true}-> componentWillUpdate()【新版删除3】->render()->componentDidUpdate()
  4. Unmounting【卸载过程】:componentWillUnmount

为什么Fiber Reconciler要有新的生命周期函数呢?

答:1.Fiber Reconciler中为了在没有更新前再次混入更新任务导致Fiber更新整个流程有点混乱;为了适配Fiber Reconciler就取消了在更新前可以再次触发更新的操作。

(有部分同学会在componentWillMount中setState;异步请求)

Fiber Reconciler要求对组件的生命周期,至少在更新前做到要纯函数行为。【不能写入异步的操作,影响更新流程】

2.我们之前并不是Fiber Reconciler中导致的,在刚开始接触React的时候会有大部分同学,会在componentWillMount进行set相关操作(setState,进行初始化redux操作,以及调用接口异步操作)【应该写在构造函数constructor中】,不然会多进行一遍vDom diff;

另一个就是componentWillUpdate中进行setState操作【不带任何条件的操作】,相当于触发了一个无线循环。

总结:基于这两点,一个是我们在老的生命周期中对一些方法的滥用,以及为了适配Fiber Reconciler当中更新前的一些流程处理,是为了我们后面的异步渲染做准备,所以React16.x之后就更新了新的生命周期函数。

 

新的组件生命周期

React v16.3版本

static getDerivedStateFromProps(props, state)【替换componentWillReceiveProps】、static getSnapshotBeforeUpdate【静态方法,静态方法中不能调用this】

1.挂载时:constructor()【构造函数】->getDerivedStateFromProps()【新增1】->render()->React更新DOM和refs->componentDidMount()

2.更新时:New Props触发更新 =>getDerivedStateFromProps()【新增1】->shouldComponentUpdate(){return true}->render()->getSnapshotBeforeUpdate()【新增2】->React更新DOM和refs->componentDidUpdate()

setState()触发更新=>shouldComponentUpdate(){return true}->render()->getSnapshotBeforeUpdate()【新增2】->React更新DOM和refs->componentDidUpdate()

forceUpdate()触发更新=>render()->getSnapshotBeforeUpdate()【新增2】->React更新DOM和refs->componentDidUpdate()

3.卸载时:componentWillUnmount()

Rebder(更新)阶段【render()方法之前】”:纯净【纯函数】且不包含副作用【重新触发setState、异步请求、redux更新】。可能会被React暂停,中止或重新启动。

Pre-commit阶段”:可以读取DOM

Commit阶段”:可以使用DOM,运行副作用,安排更新。

React v16.4版本【通常用的v16.4版本】

与v13比

挂载阶段【constructor】和更新阶段【New Props,setState(),forceUpdate()】之后都会触发getDerivedStateFromProps()

getDerivedStateFromProps

是一个派生state,所有可能触发state变更的都会经过这个静态方法,主要是返回一个派生类的state

 

挂载阶段

挂载阶段的函数

  • constructor 构造函数,初始化state,以及为事件处理函数绑定实例。【初始化数据】
  • getDerivedStateFromProps (nextProps, state) { this === window } 新增的静态方法。返回一个新的state,或者是null(后续不更新)。
  • render 渲染函数。
  • componentDidMount 挂载成功后立即调用的函数。【副作用操作,调用fetch(接口数据),绑定真实dom数据,如window.onresize,window.onscroll事件等】

更新阶段

更新阶段的函数

  • getDerivedStateFromProps props变化或者state方法触发。
  • shouldComponentUpdate 判断是否进行更新。【可以对UI更新逻辑进行优化】
  • render 渲染函数。
  • getSnapshotBeforeUpdate render方法之后调用,返回一个dom更改之前的快照,将配合后续的componentDidUpdate方法使用。
  • componentDidUpdate(oldprops, oldstate) 更新后会被立即调用。如果设置了getSnapshotBeforeUpdate(),会多出一个componentDidUpdate(oldprops, oldstatesnapshot);异步,进行setState操作,要进行条件判断,避免死循环更新,

卸载阶段

卸载阶段的函数

  • componentWillUnmount 卸载函数,组件卸载及销毁之前直接调用。主要用于清除一些在组件生命周期订阅,真实DOM事件以及setTimeout/setInterval的返回值。【不做的话,可能会引起内存泄漏、溢出】

异常捕获

v16.x 异常捕获的函数【全局错误处理,后代组件异常处理】

  • componentDidCatch(error,info) 生命周期方法在后代组件抛出错误后被调用。方法接收两个参数(error,info),分别是错误信息和错误组件的栈信息。;做一些错误日志上传,错误信息,错误源。不推荐在这里修改state,处理UI页面展示。避免setState影响Fiber 协调
  • getDerivedStateFromError(error) 在后代组件抛出错误后调用,接收一个参数(error)表示具体错误信息。做一些兼容错误页面,返回一些对象,控制页面元素,用户体验更好,是否出现不可抗性错误。新增的静态类型,返回一个派生类的state,建议在这里修改state进行页面处理

v15.x之前的处理方案:

1.关键代码加try{}catch(e){}包裹

2.监听window.onerror方案。也可以通过window.addEventListener("error", function(evt){})

3.react 提供的一个内置捕获错误方法:unstable_handleError;没有正式对外宣布过,并不是一个标准的稳定的方法

新版组件升级

升级组件版本

  • componentWillMount
    • render方法之前调用,在此调用setState并不会触发再次渲染。
    • 通常会在这个方法中进行页面标题的一些修改以及其他与再次render不相关的操作。
  • UNSAFE_componentWillMount(不推荐用这个替换componentWillMount)
    • 与state相关的操作挪到constructor方法中执行。
    • 异步操作挪到componentDidMount中执行。
  • componentWillUpdate
    • 在组件收到新的props或者state时,会在渲染之前调用。
    • 方法内不能调用setState,触发循环,内存泄漏。
  • UNSAFE_componentWillUpdate(官方保留方法,不推荐使用)
    • 应该在shouldComponentUpdate中判断是否更新。
  • componentWillReceiveProps
    • 接收父级组件传递过来最新的props,转化为组件内的state。
    • 判断是否进行更新或者执行异步请求数据。
  • UNSAFE_componentWillReceiveProps(官方保留方法,不推荐使用)
    • 与渲染相关的props直接渲染,不需要处理为组件内state。
    • 异步数据请求在componentDidUpdate中处理。
    • getDerivedStateFromProps方法替换,需要考虑生命周期的执行顺序。【挂载阶段【constructor】和更新阶段【New Props,setState(),forceUpdate()】之后都会触发getDerivedStateFromProps()

APP.js

import React, { Component } from "react";
import NewCycle from "./component";
import "./styles.css";
const mockList = [
  {
    key: 1,
    text: "这是列表项-1"
  },
  {
    key: 2,
    text: "这是列表项-2"
  },
  {
    key: 3,
    text: "这是列表项-3"
  },
  {
    key: 4,
    text: "这是列表项-4"
  }
];
export default class App extends Component {
  // let cycleList = [];
  state = {
    cycleList: []
  };
  // const [cycleList, setCycleList] = useState([]);
  queryList = () => {
    this.setState({
      cycleList: mockList
    });
  };
  render() {
    return (
      <div className="App">
        <NewCycle
          cycleList={this.state.cycleList}
          queryListCB={this.queryList}
        />
      </div>
    );
  }
}

component.js

import React, { Component } from "react";
import shallowequal from "shallowequal";// 开源第三方库,shallowequal比较值相等,或者对象含有相同的属性、且属性值相等
export default class NewCycle extends Component {
  constructor(props) {
    super(props);
    this.state = {
      list: [],
      parentList: []
    };
  }
  /* 
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (!shallowequal(this.props, nextProps)) {
      const { cycleList } = nextProps;
      this.setState({
        list: cycleList.map(item => ({
          ...item,
          label: "origin" // 组件内部要调用一些逻辑
        }))
      });
    }
  } 
  
  componentDidUpdate(prevProps, prevState) {
    // console.log(prevProps, prevState, this.props, this.state);
    // 比getDerivedStateFromProps晚一些,更新完成之后才触发
    if (!shallowequal(this.props, prevProps)) {
      const { cycleList } = this.props;
      this.setState({
        list: cycleList.map((item) => ({
          ...item,
          label: "标题"
        }))
      });
    }
  }
  */
  static getDerivedStateFromProps(props, state) {// newprops,oldstate
    // 触发时机有4种,要做好兼容判断
    const { cycleList } = props;
    const { parentList } = state;
    /**
     * prueComponent 在这里如果返回有数据的对象,
     * shouldComponentUpdate 会返回true
     * 最好是不要再用state来控制
     */
    //  初始化不执行         &&
    if (cycleList.length > 0 && !shallowequal(cycleList, parentList)) {
      return {
        list: cycleList.map((item) => ({
          ...item,
          label: "标题"
        })),
        parentList: cycleList
      };
    }
    return null;
  }
  
  queryList = () => {
    const { queryListCB } = this.props;
    if (typeof queryListCB === "function") {
      queryListCB();
    }
  };
  render() {
    const { list } = this.state;
    return (
      <div>
        {list.map(item => (
          <div key={item.key}>
            {item.label}-{item.text}
          </div>
        ))}
        <button onClick={this.queryList}>按钮</button>
      </div>
    );
  }
}

升级组件遍布-保留选项

老工程代码量很多,改动特别麻烦。需要回归的点非常多!怎么解决?

npx react-codemod rename-unsafe-lifecycles 
// 此方法会给需要添加'UNSAFE_'的方法加上它。 此时版本为【v16.x】 (v15.x < v16.x < v17)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/964961.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Backtrader中文文档专栏订阅须知

由于CSDN新出的扣费机制过于强盗&#xff0c;您通过平台支付的金额只有50%是我的。针对本专栏&#xff0c;如果您有付费意愿&#xff0c;建议通过我的淘宝小店完成支付。&#xff08;我已调整本专栏在CSDN上的售价&#xff09; 之所以如此安排&#xff0c;主要是考虑到文档凝聚…

什么是jvm

一、初识JVM&#xff08;虚拟机&#xff09; JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;JVM是一种用于计算设备的规范&#xff0c;它是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 引入Jav…

Java中的动态代理(JDK Proxy VS CGLib)

前言 动态代理可以说是Java基础中一个比较重要的内容&#xff0c;这块内容关系到Spring框架中的AOP实现原理&#xff0c;所以特别写了一篇作为个人对这块知识的总结。这部分内容主要包括&#xff1a;JDK Proxy和CGLib的基本介绍、二者的实现原理、代码示例等。 什么是动态代理…

【python爬虫】9.带着小饼干登录(cookies)

文章目录 前言项目&#xff1a;发表博客评论post请求 cookies及其用法session及其用法存储cookies读取cookies复习 前言 第1-8关我们学习的是爬虫最为基础的知识&#xff0c;从第9关开始&#xff0c;我们正式打开爬虫的进阶之门&#xff0c;学习爬虫更多的精进知识。 在前面几…

PY32F003F18点灯

延时函数学习完之后&#xff0c;可以学习PY32F003F18的GPIO输出功能。 1、Debug引脚默认被置于复用功能上拉或下拉模式&#xff1a;PA14默认为SWCLK: 置于下拉模式PA13默认为SWDIO: 置于上拉模式PF4默认为Boot&#xff1a;Boot引脚默认置于输入下拉模式 2、GPIO输出状态&#…

Prometheus+grafana安装配置

Prometheus安装配置 Prometheus下载地址 官方地址&#xff1a;Download | Prometheus 可根据系统版本下载想要的安装包&#xff0c;复制链接地址 wget https://github.com/prometheus/prometheus/releases/download/v2.33.3/prometheus-2.33.3.linux-amd64.tar.gzwg 解压pr…

protues仿真时有时候串口虚拟中端不弹窗的问题

在使用proteus的时候&#xff0c;有时候你会发现点击调试开始运行后&#xff0c;串口虚拟终端没有自动弹窗的问题&#xff0c;其实照成这种现象的原因是你在使用的过程中移动了器件位置或者是对整个视窗使用鼠标滚动进行缩放了&#xff0c;如果要重新弹窗则需要进行以下操作: …

手撕 视觉slam14讲 ch13 代码(2)基本类的抽象

在正式写系统之前&#xff0c;我们在上一篇分析了基本的3个类&#xff1a;帧、2D特征点、3D地图点&#xff0c;这次我们开始代码实现这些基本数据结构&#xff1a; 1.帧类 常见的SLAM系统中的帧&#xff08;Frame&#xff09;需要包含以下信息&#xff1a;id&#xff0c;位姿…

容器技术Linux Namespaces和Cgroups

对操作系统了解多少&#xff0c;仅仅敲个命令吗 操作系统虚拟化&#xff08;容器技术&#xff09;的发展历程 1979 年&#xff0c;UNIX 的第 7 个版本引入了 Chroot 特性。Chroot 现在被认为是第一个操作系统虚拟化&#xff08;Operating system level virtualization&#x…

CSS使两个不同的div居中对齐的三种解决方案

在CSS中&#xff0c;有多种方法可以让两个不同的div居中对齐&#xff0c;包括相对定位和绝对定位。以下是两种常见的方法&#xff1a; 方法一&#xff1a;使用Flexbox Flexbox是一个用于创建灵活布局的CSS3模块。使用Flexbox&#xff0c;可以很容易地对元素进行居中对齐。 H…

C++基础语法——多态

1.什么是多态&#xff1f; 多态是面向对象编程中的一个概念&#xff0c;它允许不同的对象对同一个消息作出不同的响应。简单来说&#xff0c;多态是指同一种操作或方法可以在不同的对象上产生不同的行为。这种灵活性使得代码更加可扩展和可维护。在多态中&#xff0c;对象的类型…

弯道超车必做好题集锦三(C语言编程题)

目录 前言&#xff1a; 1.单词倒排 方法1&#xff1a;scanf匹配特定字符法 方法2&#xff1a; 双指针法 2.统计每个月兔子的总数 方法1&#xff1a;斐波那契数列 方法2&#xff1a;斐波那契的递归 3.珠玑妙算 方法&#xff1a;遍历 4.寻找奇数&#xff08;单身狗&#…

【图解算法数据结构】分治算法篇 + Java代码实现

文章目录 一、重建二叉树二、数值的整数次方三、打印从 1 到最大的 n 位数四、二叉搜索树的后序遍历序列五、数组中的逆序对 一、重建二叉树 public class Solution {int[] preorder;HashMap<Integer, Integer> dic new HashMap<>();public TreeNode buildTree(in…

可视化流程设计平台有啥优势?

在流程化办公发展趋势逐渐明朗的今天&#xff0c;运用什么样的平台可以帮助广大用户朋友实现这一目标&#xff1f;可视化流程设计平台是轻量级、更灵活、易操作、效率高的平台&#xff0c;可以快速定制客户专属的框架平台&#xff0c;为每一位客户朋友做好数据管理&#xff0c;…

【小沐学Unity3d】3ds Max 骨骼动画制作(蒙皮修改器skin)

文章目录 1、简介2、蒙皮修改器3.1 骨骼对象测试3.2 Biped对象测试 3、动画制作4、FBX导出结语 1、简介 “蒙皮”修改器是一种骨骼变形工具&#xff0c;主要设计用于通过另一个对象对一个对象进行变形来创建角色动画。可使用骨骼、样条线和其他对象变形网格、面片和 NURBS 对象…

【Java 基础篇】Java 数组使用详解:从零基础到数组专家

如果你正在学习编程&#xff0c;那么数组是一个不可或缺的重要概念。数组是一种数据结构&#xff0c;用于存储一组相同类型的数据。在 Java 编程中&#xff0c;数组扮演着非常重要的角色&#xff0c;可以帮助你组织、访问和操作数据。在本篇博客中&#xff0c;我们将从零基础开…

如何使用C++11原子操作实现自旋锁

什么是自旋锁&#xff1f; C自旋锁是一种低层次的同步原语&#xff0c;用于保护共享资源的访问。自旋锁是一种轻量级的锁&#xff0c;适用于短时间的资源锁定。 自旋锁的特点&#xff1a;当一个线程尝试获取已经被另一个线程占有的自旋锁时&#xff0c;这个线程会进入一个循环…

从入门到精通,30天带你学会C++【第六天:与或非三兄弟和If判断语句(博主目前最长文章,2514字)】(学不会你找我)

目录 前言 计算机里的真和假 与或非三兄弟 ​编辑与运算&#xff08;&&&#xff09; 具体说明表格&#xff1a; 举个栗子1&#xff1a; 或运算&#xff08;||&#xff09; 具体说明表格&#xff1a; 举个栗子2&#xff1a; 非运算&#xff08;!&#xff09…

python编写MQTT订阅程序

Download | Eclipse Mosquitto 1、下载&#xff1a; https://mosquitto.org/files/binary/win64/mosquitto-2.0.17-install-windows-x64.exe 2、安装&#xff1a; 3、conf配置 1)使用notepad打开“C:\Program Files\mosquitto\mosquitto.conf”另存为c:\myapp\msquitto\mo…

C++的多重继承

派生类都只有一个基类,称为单继承(Single Inheritance)。除此之外,C++也支持多继承(Multiple Inheritance),即一个派生类可以有两个或多个基类。 多继承容易让代码逻辑复杂、思路混乱,一直备受争议,中小型项目中较少使用,后来的 Java、C#、PHP 等干脆取消了多继承。 …