React18原理: 生命周期中特别注意事项
概述
- 生命周期就是一个组件从诞生到销毁的全过程(包含错误捕获,这里暂且不聊这个)
- react 在组件的生命周期中注册了一系列的钩子函数
- 支持开发者在其中嵌入代码,并在适当的时机运行
- 生命周期本质上就是组件中的钩子函数,主要有三个主要的钩子
- 挂载
- 更新
- 卸载
首次挂载
-
1 )初始化 constructor
- 同一个类组件对象只会运行一次
- 所以经常来做一些初始化的操作
- 同一个组件对象被多次创建,它们的 constructor 互不干扰
- 注意
- 在 constructor 中尽量避免(禁止) 使用 setState
- setState会造成页面的重新渲染
- 但是在 初始化 阶段,页面都还没有将真实dom挂载到页面上,是没有任何重新渲染的意义的
- 除异步情况,比如 setInterval 中使用 setState 是没问题的,
- 因为在执行的时候页面早已渲染完成,但也最好不要使用,容易引起奇怪的问题,参考
constructor(props) {super(props);this.state = {num: 1}// 不可以,直接warningthis.setState({num: this.state.num + 1});// 可以使用,但不建议setInterval(() => {this.setState({num: this.state.num + 1});}, 1000); }
-
2 )获取最新的属性和状态 static getDerivedStateFromProps
- 该方法是一个静态属性,静态属性就是为了不让使用 this 和 setState
- 在16版本之前不存在,在新版生命周期中,主要用于取代 componentWillMount 和 comonentWillReceiveProps
- 因为这两个老生命周期方法在协议开发者不规范的使用下极易产生一些反模式的 bug
- 因为是静态方法,所以,你在其中根本拿不到 this, 更不可能调用 setState
- 该方法在挂载阶段和更新阶段都会运行,它有两个参数 props 和 state 当前的属性值和状态
- 它的返回值会合并掉当前的状态 (state), 如果返回了非 Object 的值
- 那么它啥都不会做,如果返回的是 Object, 那它将会跟当前的状态合并
- 可以理解为 Object.assign, 通常情况下,几乎不怎么使用该方法
/*** 静态方法,首次挂载和更新渲染都会运行该方法 * props 当前属性 * state 当前状态 */ static getDerivedStateFromProps(props, state) {// return 1; // 没用return {num: 999, // 合并到当前 state 对象} }
-
3 )创建 vDOM render
- 最重要的生命周期,没有之一,用来生成虚拟节点vDom树
- 该方法只要遇到需要重新渲染都会运行
- 同样,在 render 中也严禁使用 setState, 因为会导致无限递归重新渲染导致 爆栈
render() {// 严禁使用this.setState({num: 1})return (<>(this.state.num)</>) }
-
4 )挂载到页面渲染成真实Dom componentDidMount
- 该方法只会运行一次,在 首次渲染 时页面将 真实 dom 挂载完毕之后运行
- 通常在这里做一些异步操作,比如开启定时器,发起网络请求,获取真实DOM等
- 在该方法中,可以大胆使用 setState, 因为页面已经渲染完成
- 执行完该钩子函数后,组件正式进入到 活跃 状态
componentDidMount() {// 初始化或异步代码this.setState({})setInterval(() => {}); // 简单模拟document.querySelectorAll('div'); }
更新阶段
-
更新阶段会更新 state 或 更新 props
-
1 )获取最新的属性和状态 static getDerivedStateFromProps
-
2 )是否重新渲染 shouldComponentUpdate
- 在执行完 static getDerivedStateFromProps 后,会执行该钩子函数
- 该方法通常用来做 性能优化,它的返回值 (boolean) 决定了是否要进行 渲染 更新
- 该方法有两个参数 nextProps 和 nextState 表示此次更新(下一次)的属性和状态
- 通常,我们会将当前值与此次要更新的值做比较来决定是否要进行重新渲染
- 在react 中,官方提供了一个基础版的优化组件 PureComponent 就是一个 HOC 高阶组件
- 内部实现就是帮我们用 shouldComponentUpdate 做了浅比较
- 注意,继承了 PureComponent 后, 不需要再使用 SCU 进行优化
/*** 决定是否要重新进行渲染* nextProps 此次更新的属性* nextState 此次更新的状态* returns boolean*/ shouldComponentUpdate(nextProps, nextState) {// 伪代码,如果当前的值和下一次的值相等,那么就没有更新渲染的必要了if (this.props === nextProps && this.state === nextState) {return false;}return true; }
-
3 )更新vDOM render
-
4 )获取更新之前的状态 getSnapshotBeforeUpdate
- 如果 shouldComponentUpdate 返回是 true,
- 那么就会运行 render 重新生成虚拟 DOM 树来进行对比更新
- 该方法运行在 render 之后,表示 真实 DOM 已经构建完成
- 但还没有渲染到页面中,可以理解为更新前的 快照,通常用来做一些附加的DOM操作
- 比如,突然想针对某个 class 的真实元素做一些事情,那么就可以在此方法中获取元素
- 并修改,该函数有两个参数 prevProps 和 prevState 表示此次更新前的属性和状态
- 该函数的返回值 snapshot,会作为 componentDidUpdate 的第三个参数
/*** 获取更新前的快照,通常用来做一些附加的DOM操作* prevProps 更新前的属性* prevState 更新前的状态*/ getSnapshotBeforeUpdate(prevProps, prevState) {// 获取真实DOM在渲染到页面前作一些附加操作...document.querySelectorAll('div').forEach(it => it.innerHTML = '123')return 'componentDidUpdate的第三个参数' }
-
5 )更新后挂载成真实DOM componentDidUpdate
- 该方法是 更新阶段 最后运行的 钩子函数,跟
getSnapshotBeforeUpdate不同的是 - 它运行时间点是在 真实DOM 挂载到页面后,通常也会使用该方法来操作一些真实的DOM
- 它有三个参数分别为: prevProps, prevState, snapshot, 跟 Snapshot 钩子函数一样
- 表示更新前的属性,状态,Snapshot 钩子函数的返回值
/*** prevProps 更新前的属性* prevState 更新前的状态* snapshot getSnapshotBeforeUpdate 的返回值*/ componentDidUpdate(prevProps, prevState, snapshot) {document.querySelectorAll('div').forEach(it => it.innerHTML = snapshot) }
- 该方法是 更新阶段 最后运行的 钩子函数,跟
卸载阶段
- 组件被卸载 componentWillUnMount
- 该 钩子函数 属于卸载阶段中唯一的方法
- 如果组件在渲染的过程中被卸载了,React会报出 Warning: Can’t perform a React state update on an unmounted component 的警告
- 所以,通常爱组件被卸载时,做清除副作用的操作
componentWillUnmount() {// 组件倍卸载前清理副作用clearInterval(timer1);clearTimeout(timer2);this.setState = () => {}; }
相关文章:
React18原理: 生命周期中特别注意事项
概述 生命周期就是一个组件从诞生到销毁的全过程(包含错误捕获,这里暂且不聊这个)react 在组件的生命周期中注册了一系列的钩子函数支持开发者在其中嵌入代码,并在适当的时机运行生命周期本质上就是组件中的钩子函数,主要有三个主要的钩子 挂…...
【C语言】Linux内核bind系统调用代码
一、Linux 4.9内核bind系统调用代码注释 int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) {struct socket *sock; // 定义socket对象的指针struct sockaddr_storage address; // 用于存储从用户空间复制过来的地址int err…...
Ubuntu下Anaconda+PyCharm搭建PyTorch环境
这里主要介绍在condapytorch都正确安装的前提下,如何通过pycharm建立开发环境; Ubuntu下AnacondaPyCharm搭建PyTorch环境 系统环境:Ubuntu22.04 conda: conda 23.11.0 pycharm:如下 condapytorch的安装教程介绍,请点击这里&…...
酷开科技荣获“消费者服务之星”称号后的未来展望
恭喜酷开科技荣获2023年第四季度黑猫平台“消费者服务之星”称号!这是对酷开科技长期以来坚持用户至上、用心服务的肯定和认可。作为OTT行业的佼佼者,酷开科技一直秉承着“以用户为中心”的服务理念,不断追求卓越品质,为用户提供更…...
UVA1449 Dominating Patterns 题解
UVA1449 Dominating Patterns 题解 板子题诶。 解法 AC 自动机模板题,因为数据范围比较小,所以不加拓扑排序优化建图即可通过本题。这里简单介绍一下拓扑排序优化建图。 在查找时,每次都暴力的条 f a i l fail fail 指针是很消耗时间的&…...
【C语言】数据结构#实现堆
目录 (一)堆 (1)堆区与数据结构的堆 (二)头文件 (三)功能实现 (1)堆的初始化 (2)堆的销毁 (3)插入数据 …...
AES加密中的CBC和ECB
目录 1.说明 2.ECB模式(base64) 3.CBC模式 4.总结 1.说明 AES是常见的对称加密算法,加密和解密使用相同的密钥,流程如下: 主要概念如下: ①明文 ②密钥 用来加密明文的密码,在对称加密算…...
【C++】类和对象(四)
前言:在类和对象中,我们走过了十分漫长的道路,今天我们将进一步学习类和对象,类和对象这块荆棘地很长,各位一起加油呀。 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:高质量&a…...
XGB-5: DART Booster
XGBoost 主要结合了大量的回归树和一个小的学习率。在这种情况下,早期添加的树是重要的,而晚期添加的树是不重要的。 Vinayak 和 Gilad-Bachrach 提出了一种将深度神经网络社区的 dropout 技术应用于梯度提升树的新方法,并在某些情况下报告了…...
HiveSQL——不使用union all的情况下进行列转行
参考文章: HiveSql一天一个小技巧:如何不使用union all 进行列转行_不 union all-CSDN博客文章浏览阅读881次,点赞5次,收藏10次。本文给出一种不使用传统UNION ALL方法进行 行转列的方法,其中方法一采用了concat_wsposexplode()方…...
Python环境下基于指数退化模型和LSTM自编码器的轴承剩余寿命预测
滚动轴承是机械设备中关键的零部件之一,其可靠性直接影响了设备的性能,所以对滚动轴承的剩余使用寿命(RUL)进行预测是十分必要的。目前,如何准确地对滚动轴承剩余使用寿命进行预测,仍是一个具有挑战的课题。对滚动轴承剩余寿命评估…...
无人机竞赛视觉算法开发流程开源计划(询问大家意见)
本科中参加过一系列的无人机机器人竞赛,像电赛、工训赛、机器人大赛这些,有一些比较常用的方案打算开源一下。现在读研了,也算是对本科的一个总结,但是还是想看看大家意见,大家有什么需求可以在评论区说,我…...
DMA直接内存访问,STM32实现高速数据传输使用配置
1、DMA运用场景 随着智能化、信息化的不断推进,嵌入式设备的数据处理量也呈现指数级增加,因此对于巨大的数据量处理的情况时,必须采取其它的方式去替CPU减负,以保证嵌入式设备性能。例如SD卡存储器和音视频、网络高速通信等其它情…...
Web安全研究(六)
文章目录 HideNoSeek: Camouflaging(隐藏) Malicious JavaScript in Benign ASTs文章结构Introjs obfuscationmethodologyExample HideNoSeek: Camouflaging(隐藏) Malicious JavaScript in Benign ASTs CCS 2019 CISPA 恶意软件领域,基于学习的系统已经非常流行&am…...
python3 中try 异常调试 raise 异常抛出
一、什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。 一般情况下,在Python无法正常处理程序时就会发生一个异常。 异常是Python对象,表示一个错误。 当Python脚本发生异常时我…...
Java中的序列化是什么?如何实现对象的序列化和反序列化?请解释Serializable接口的作用是什么?请解释transient关键字的作用是什么?为什么会使用它?
Java中的序列化是指将对象转换为字节序列的过程,以便可以在网络上传输或将其保存到持久存储介质中。反序列化则是将字节序列重新转换回对象的过程。Java提供了一种称为序列化(Serialization)的机制来实现对象的序列化和反序列化。 要实现对象…...
二维差分---三维差分算法笔记
文章目录 一.二维差分构造差分二维数组二维差分算法状态dp求b[i][j]数组的二维前缀和图解 二.三维前缀和与差分三维前缀和图解:三维差分核心公式图解:模板题 一.二维差分 给定一个原二维数组a[i][j],若要给a[i][j]中以(x1,y1)和(x2,y2)为对角线的子矩阵中每个数都加上一个常数…...
D. Divisible Pairs
思路:我们预处理出每个数分别摸上xy的值,用map存一下,然后遍历每个数,如果a b是x的倍数的话,那么他们模x的值相加为x,如果a - b是y的倍数的话,那么他们的模y的值相等。 代码: voi…...
【教程】Kotlin语言学习笔记(二)——数据类型(持续更新)
写在前面: 如果文章对你有帮助,记得点赞关注加收藏一波,利于以后需要的时候复习,多谢支持! 【Kotlin语言学习】系列文章 第一章 《认识Kotlin》 第二章 《数据类型》 文章目录 【Kotlin语言学习】系列文章一、基本数据…...
react 插槽
问题开发当中会经常出现组件十分相似的组件,只有一部分是不同的 解决: 父组件:在引用的时候 import { Component } from "react"; import Me from "../me";const name <div>名称</div> class Shoop extends Compone…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
