react类式组件的生命周期和useEffect实现函数组件生命周期
概念
生命周期是一个组件丛创建,渲染,更新,卸载的过程,无论是vue还是react都具有这个设计概念,也是开发者必须熟练运用的,特别是业务开发,不同的生命周期做不同的事是很重要的.
....
多说两句心得,本人是先接触vue的,无论是vue2还是vue3的生命周期,在理解和学习上都会比react更容易理解,我在学习react的时候,也经常会想着这个api如果在vue里面会和哪个api功能相同.
其实有些本末倒置了,先有react才有的vue,vue是作者做了更多的操作,让你用到更舒适的api,还是那个经典形容,react是手动打,vue是自动挡.
废话不多说,开始说react的生命周期
...
如果想直接死记硬背八股文,直接拉到底看总结就可以了
类式组件
在hooks出来之前,写react基本都是用类式组件
两个原因,一是对this这个东西有特别的喜爱(vue后遗症),二是类式组件可以使用生命周期和state,适合开发业务组件.
测试各个钩子函数的demo
import React, { Component} from 'react'
export default class index extends Component {constructor(){super()console.log(this,'constructor---构造器')}state = {num:1}add = ()=>{let newNum = this.state.num +1this.setState({num:newNum})}//生命周期钩子(旧的)
// componentWillMount =()=>{
// console.log('componentWillMount---组件将要加载')
// }// componentWillUpdate = ()=>{
// console.log('componentWillUpdate','组件将要更新')
// }//生命周期钩子(新的)
static getDerivedStateFromProps = ()=>{console.log(this,'getDerivedStateFromProps---初始化一些基础状态')return null
}getSnapshotBeforeUpdate = ()=>{console.log(this,'getSnapshotBeforeUpdate---更新之前的快照')return '旧的值'
}//新旧都具备的shouldComponentUpdate = ()=>{console.log(this,'shouldComponentUpdate','组件需要更新')return true}componentDidUpdate = ()=>{console.log(this,'componentDidUpdate','组件更新完毕')}componentDidMount = ()=>{console.log(this,'componentDidMount---组件加载完成')}updateCallBack = ()=>{this.forceUpdate()}render() {console.log(this,'render---渲染函数')return (<div id='index'><h3>生命周期模块</h3> <button onClick={this.add}>修改一下数值</button><p>{this.state.num}</p><button onClick={this.updateCallBack}>手动更新</button><br /></div>)}componentWillUnmount = ()=>{console.log(this,'componentWillUnmount---组件将要卸载')}
}
场景:
1.页面初次加载
constructor > getDerivedStateFromProps > render > componentDidMount

2.点击修改一下数值按钮
getDerivedStateFromProps > shouldComponentUpdate > render > getSnapshotBeforeUpdate >
componentDidUpdate

3.手动更新(forceUpdate函数)
getDerivedStateFromProps > render > getSnapshotBeforeUpdate > componentDidUpdate

4.卸载当前组件
componentWillUnmount

生命周期经典图

解读一下:
好吧,其实没有什么太多好解读的,本人的react内力没有那么深厚,这张图就是刚才我们实验的结果
初始化,自动更新,手动更新,卸载
你只要把这个demo自己写一下,就瞬间知道这个图是干啥的了,除了很长的单词比较难写,其余都好说.
你以为这样就完了吗,不不不,没有没有没有.这里还有两个需要专门说的
两个疑问
1.生命周期连续调用了两次的问题

造成这个原因是因为你的根组件使用了严格模式 React.StrictMode
ReactDOM.createRoot(document.getElementById('root')).render(<Provider store={store}>{/* <React.StrictMode> 把它注释掉就可以了*/} <App />{/* </React.StrictMode> */}</Provider>
)
2.父子组件生命周期顺序(测试demo)
初始化
父costructor > 父 getDerviedStateFromProps > 父render >子costructor >子getDerviedStateFromProps > 子render > 子componentDidMount >父componentDidMount

父组件修改值触发更新
父 getDerivedStateFromProps > 父 shouldComponentUpdate > 父 render > 子 getDrivedStateFromprops > 子shouldComponentUpdate > 子 render > 子 getSnaphotBeforeUpdate > 父getSnapshotBeforeUpdate > 子 componentDidUpdate> 父 componentDidUpdate

父组件手动更新
父 getDerivedStateFromProps > 父render > 子 getDerivedStateFromProps > 子 shouldComponentUpdate > 子render > 子getSnapshotBeforeUpdate > 父getSnapshotBeforeUpdate > 子componentDidUpdate > 父componentDidUpdate

组件卸载
父componentWillUnmount > 子componentWillUnmount

函数组件
函数组件实现生命周期是需要借助一个api的,这个api叫做useEffect.
demo
import React,{useState,useEffect} from 'react'
import {Button} from 'antd'
export default function index(props) {const [num1,changeNum1] = useState(0)const [num2,changeNum2] = useState(10)//单个-----------------------------------------------------//首次加载,修改num1,修改num2,卸载当前组件没有useEffect(()=>{console.log('只传一个函数')})//首次加载,num1没有,num2没有,卸载当前组件没有useEffect(()=>{console.log('参数二传一个空数组')},[])//首次加载,修改num1,num2没有,卸载当前组件没有useEffect(()=>{console.log('传参数num1')},[num1])//首次加载,num1没有,修改num2,卸载当前组件没有useEffect(()=>{console.log('传参数num2')},[num2])//首次加载,修改num1,修改num2,卸载当前组件没有useEffect(()=>{console.log('都传')},[num1,num2])//首次没有,修改num1,修改num2,卸载组件调用useEffect(()=>{return ()=>{console.log('return方法')}})// 总结:// 1.参数1:函数: 初始化和每次修改参数都会触发这个函数// 2.参树2:空数组: 只有首次加载会触发// 3.参数2:某条数据: 首次加载和修改该数据都会触发// 4.参数2:多条数据: 首次加载和修改数组内任意一条数据都会触发// 5.参数1:函数返回一个函数: 首次不急在,但是修改任意数值和卸载组件时都会调用return (<div><p>数值1:{num1}<Button onClick={()=>changeNum1(num1+1)}>修改数值1</Button></p><p>数值2:{num2}<Button onClick={()=>changeNum2(num2-1)}>修改数值2</Button></p></div>)
}
初始化

修改值1

组件卸载

实现初始化,更新,单独的数据更新,卸载
import React,{useState,useEffect} from 'react'
import {Button} from 'antd'
export default function index(props) {const [num1,changeNum1] = useState(0)const [num2,changeNum2] = useState(10)// 组合------------------------------------------------------// 场景1: 初始化加载useEffect(()=>{console.log('初始化加载')console.log(num1,'???',props)},[])//场景2: 任意数据更新,但是初始化不加载useEffect(()=>{return ()=>{console.log('数据发生修改了')}})//场景3: 只有卸载时加载useEffect(()=>{return ()=>{console.log('卸载才会调用')}},[])//场景4: 某一数据发生改变,单独触发useEffect(()=>{return ()=>{console.log('只有修改num1才会调用')}},[num1])return (<div><p>数值1:{num1}<Button onClick={()=>changeNum1(num1+1)}>修改数值1</Button></p><p>数值2:{num2}<Button onClick={()=>changeNum2(num2-1)}>修改数值2</Button></p></div>)
}
总结
类式组件
各阶段钩子调用顺序
| 初始化 | constructor > getDerivedStateFromProps > render > componentDidMount |
| 自动更新 | getDerivedStateFromProps > shouldComponentUpdate > render > getSnapshotBeforeUpdate > componentDidUpdate |
| 手动更新 | getDerivedStateFromProps > render > getSnapshotBeforeUpdate > componentDidUpdate |
| 卸载 | componentWillUnmount |
父子组件生命周期
| 初始化 | 父costructor > 父 getDerviedStateFromProps > 父render >子costructor >子getDerviedStateFromProps > 子render > 子componentDidMount >父componentDidMount |
| 父组件自动更新 | 父 getDerivedStateFromProps > 父 shouldComponentUpdate > 父 render > 子 getDrivedStateFromprops > 子shouldComponentUpdate > 子 render > 子 getSnaphotBeforeUpdate > 父getSnapshotBeforeUpdate > 子 componentDidUpdate> 父 componentDidUpdate |
| 父组件手动更新 | 父 getDerivedStateFromProps > 父render > 子 getDerivedStateFromProps > 子 shouldComponentUpdate > 子render > 子getSnapshotBeforeUpdate > 父getSnapshotBeforeUpdate > 子componentDidUpdate > 父componentDidUpdate |
| 卸载 | 父componentWillUnmount > 子componentWillUnmount |
钩子函数连续调用两次的问题解决
干掉根组件的 React.StrictMode
函数组件
| 只在初始化加载调用 | useEffect(()=>{ console.log('初始化加载') },[]) |
| 初始化不调用但是更新组件会调用 | useEffect(()=>{ return ()=>{ console.log('数据发生修改了') } }) |
| 单独的数据发生变化进行调用 | useEffect(()=>{ return ()=>{ console.log('只有修改num1才会调用') } },[num1]) |
| 只在组件卸载时调用 | useEffect(()=>{ return ()=>{ console.log('卸载才会调用') } },[]) |
尾声
我的这篇博客没有专门讲这些api在调用时都发生了啥,主要是让读者了解react生命周期的api调用时机,属于业务开发中实用知识点,感觉还行的看客老爷们给个赞吧!
相关文章:
react类式组件的生命周期和useEffect实现函数组件生命周期
概念 生命周期是一个组件丛创建,渲染,更新,卸载的过程,无论是vue还是react都具有这个设计概念,也是开发者必须熟练运用的,特别是业务开发,不同的生命周期做不同的事是很重要的. ....多说两句心得,本人是先接触vue的,无论是vue2还是vue3的生命周期,在理解和学习上都会比react更…...
ARM 基础学习记录 / 异常与GIC介绍
GIC概念 念课本(以下内容都是针对"通用中断控制器(GIC)"而言,直接摘录的,有的地方可能不符人类的理解方式): 通用中断控制器(GIC)架构提供了严格的规范&…...
java压缩pdf体积,图片体积
pdf整体进行压缩,图片进行压缩 // 生成主证书的PDF路径 创建一个文件String pdfPath UploadDown.createFile(".pdf");outputStream new FileOutputStream(pdfPath);bufferedOutputStream new BufferedOutputStream(outputStream);writer PdfWriter.getInstance(…...
Ubuntu(WSL2) 安装最新版本的 GCC
要在 Ubuntu 上安装最新版本的 GCC,可以通过以下步骤进行操作: 1. 打开终端(Terminal) 2. 更新软件包列表,确保系统使用最新的软件包信息,运行以下命令: sudo apt update 3. 安装 GCC 软件包…...
lua 时间差功能概略
简介 在进行程序设计过程中,经常需要对某些函数、某些程序片断从开始运行到运行结束所耗费的时间进行一些量化。这种量化实际上就是计算时间差。 获取函数耗时情景如下: function time_used() --开始计时-- do something at here. --结束计时--时间差&…...
【C++11】左值引用,右值引用,移动/复制构造,完美转发
左值与右值 字面意思是可以放在等号左边的就是左值,只能放在等号右边的就是右值(为何是“可以”“只能”?例如i是左值,但他依然可以放在等号右边)。 严格上的定义:可以取地址的就是左值,反之为…...
解决找不到x3daudio1_7.dll的方法,快速解决x3daudio1_7.dll丢失问题
在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是“找不到x3daudio1_7.dll”。这个问题可能是由于多种原因引起的,例如文件丢失、损坏或被病毒感染等。下面将详细介绍如何解决这个问题。 首先,我们需要了解x3daudio1_…...
LeetCode:2300. 咒语和药水的成功对数(C++)
目录 2300. 咒语和药水的成功对数 题目描述: 实现代码与解析: 二分 原理思路: 2300. 咒语和药水的成功对数 题目描述: 给你两个正整数数组 spells 和 potions ,长度分别为 n 和 m ,其中 spells[i] 表…...
【Spring生命周期核心底层源码之剖析】
文章目录 一、Spring生命周期核心底层源码剖析—扫描1.1、Spring底层扫描机制doScan方法源码剖析 一、Spring生命周期核心底层源码剖析—扫描 1.1、Spring底层扫描机制doScan方法源码剖析 其源代码如下: protected Set<BeanDefinitionHolder> doScan(Strin…...
关于Thread.sleep方法的一些使用
Thread.sleep方法的作用就是使当前线程暂停执行一段指定的时间。 它的参数是以ms为单位的时间参数,表示暂停时间长度。如Thread.sleep(1000);表示暂停1s。 这个方法通常用在以下一些情况: 1、模拟延迟:在某些情况下,我们希望在…...
MeterSphere | 前端入参加密
项目场景: 在 MeterSphere 开源框架中,解决前端手机号入参加密 解决方案: 导入 JavaScript 包采用加密算法 导入网上 JavaScript 包 // 1. 通过cdn加载网上的js文件 g new Packages.org.mozilla.javascript.tools.shell.Global(Packages.o…...
微服务如何做负载均衡?
笔者在参与联通某子公司时,遇到了这样一个问题。感觉比较实际,特来记录一波。 先看腾讯混元的解答: 微服务架构中,负载均衡是必不可少的。在微服务中,负载均衡可以通过以下几种方式来实现: 1. DNS轮询&am…...
C++高级编程:构建高效稳定接口与深入对象设计技巧
C高级编程:构建高效稳定接口与深入对象设计技巧 建立稳定接口 类是C中的主要抽象单位。你应该将抽象原则应用于你的类,尽可能将接口与实现分离。具体来说,你应该使所有数据成员私有,并可选择性地提供getter和setter方法。这就是…...
Qt——连接mysql增删查改(仓库管理极简版)
目录 UI布局设计 .pro文件 mainwindow.h main.cpp UI布局设计 .pro文件 QT core gui QT core gui sql QT sqlgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any …...
Panda3d 场景管理
Panda3d 场景管理 文章目录 Panda3d 场景管理有关分层场景图的重要信息NodePathNodePath 以及 Node 的函数调用模型文件文件格式加载模型文件将模型放置在场景图中模型缓存压缩模型异步加载模型通过回调函数进行 常见的状态变化修改节点的位置和姿态改变父级节点改变颜色隐藏和…...
京东数据分析(京东销量):2023年9月京东投影机行业品牌销售排行榜
鲸参谋监测的京东平台9月份投影机市场销售数据已出炉! 根据鲸参谋电商数据分析平台的相关数据数据显示,9月份,京东平台投影机的销量为13万,环比下滑约17%,同比下滑约25%;销售额将近2.6亿,环比下…...
uniapp cli化一键游项目启动报错总结
问题1、使用hbuilder运行指令,开始编译后没有反应,使用命令构建自行结束进程 解决:因为使用了node16.24,卸载重新安装14.17后解决 问题2、 21:31:11.483 Module build failed (from ./node_modules/vue/cli-service/node_module…...
我的月光宝盒初体验失败了
哈哈哈,我爱docker, docker 使我自由!!! docker make me free! 菠萝菠萝蜜口号喊起来。 https://github.com/vivo/MoonBox/ windows上安装好了docker之后,docker-compose是自带的。 docker-compose -f docker-compo…...
vue3+vite搭建后台项目-1 引入element-plus 中文包,打包时报错问题
vue3vite搭建后台项目-1 引入element-plus 中文包,打包时报错问题 终端报错 If theelement-pluspackage actually exposes this module, try adding a new declaration (.d.ts) file containing are moduleelement-plus/dist/locale/zh-cn.mjsdec import zhCn fromelement-plus…...
带你详细了解git的【分支和标签】
🏅我是默,一个在CSDN分享笔记的博主。📚📚 🌟在这里,我要推荐给大家我的专栏《git》。🎯🎯 🚀无论你是编程小白,还是有一定基础的程序员,…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
