【react全家桶学习】react的 (新/旧) 生命周期(重点)
目录
生命周期(旧)
挂载时的生命周期
constructor(props)
componentWillMount()-------------新生命周期已替换
render()
componentDidMount()--- 组件挂载完毕的钩子
渲染时的生命周期
componentWillReceiveProps (nextProps)------------------新生命周期已替换 ,父组件渲染的时候子组件会调用,组件将要接收新的props的钩子
shouldComponentUpdate(nextProps,nextState)----调用setState()时会调用,强制更新则不会触发该钩子
componetnWillUpdate(nextProps,nextState)----------------新生命周期已替换
render()
componentDidUpdate(prevProps,precState,snapshot)
方式一【调用setState触发的钩子】
方式二【调用forceUpdate触发的钩子】
生命周期(旧)总结:
生命周期(新)
react新旧生命周期区别
挂载时的生命周期
constructor --上面已讲
getDerivedStateFromProps --详细讲解
render --上面已讲
componentDidMount --上面已讲
渲染时的生命周期
getDerivedStateProps --上面已讲
shouldComponentUpdate -- 控制组件更新的开关,上面已讲
render --上面已讲
getSnapshotBeforeUpdate -- 详细讲解
componentDidUpdate--上面已讲
卸载时的生命周期
componentWillUnmount --同旧的一样,不讲喽
生命周期(新)总结:
1、初始化阶段: 由ReactDOM.render()触发---初次渲染
2,更新阶段: 由组件内部this.setSate()或父组件重新render触发
3,卸载组件: 由ReactDOM.unmountComponentAtNode()触发
重要的钩子
即将废弃的子
相对比vue的生命周期,react显得复杂的多,光从名称上就比vue长,所以做好准备,不要放弃,坚持就是胜利、
文章有点长,不要着急,常用的其实没几个,看到最后的大总结,千万不要错过呀~
React的生命周期可以分为三个阶段:挂载、渲染、卸载;
生命周期(旧)

挂载时的生命周期
以下面这个例子来讲解 ;
import React, { Component } from 'react'export default class oldIndex extends Component {constructor(props) {console.log('constructor')super(props)this.state = { count: 0 }}add = () => {const { count } = this.statethis.setState({ count: count++ })}// 组件将要挂载的钩子componentWillMount() {console.log('componentWillMount')}// 组件挂载完毕的钩子componentDidMount() {console.log('componentDidMount')}render() {console.log('render')const { count } = this.statereturn (<div><h2>当前求和为:{count}</h2><button onClick={this.add}>点我+1</button></div>)}
}
看下挂载时的生命周期打印顺序:
综上所述【挂载时】旧生命周期 调用顺序如下:
-
constructor(props)
接收props和context,当想在函数内使用这两个参数需要在super传入参数,当使用constructor时必须使用super,否则可能会有this的指向问题,如果不初始化state或者不进行方法绑定,则可以不在组件写构造函数;
注意:避免将 props 的值复制给 state!这是一个常见的错误
constructor(props) {super(props);// 不要这样做this.state = { color: props.color };
}
如此做毫无必要(可以直接使用 this.props.color),同时还产生了 bug(更新 prop 中的 color 时,并不会影响 state)。
-
componentWillMount()-------------新生命周期已替换
在挂载之前也就是render之前被调用。
在服务端渲染唯一会调用的函数,代表已经初始化数据但是没有渲染dom,因此在此方法中同步调用 setState() 不会触发额外渲染。
-
render()
render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。
-
componentDidMount()--- 组件挂载完毕的钩子
在组件挂在后(插入到dom树中)后立即调用
可以在这里调用Ajax请求,返回的数据可以通过setState使组件重新渲染,或者添加订阅,但是要在conponentWillUnmount中取消订阅
渲染时的生命周期
当组件的 props 或 state 发生变化时会触发更新。
-
componentWillReceiveProps (nextProps)------------------新生命周期已替换 ,父组件渲染的时候子组件会调用,组件将要接收新的props的钩子

创建一个父组件
import React, { Component } from 'react'
import Child from './child'
export default class index extends Component {state = {name: '小锁',}changeName = () => {this.setState({name: '大锁',})}render() {return (<div><h2>父组件</h2><button onClick={this.changeName}>改名</button><Child name={this.state.name}></Child></div>)}
}
子组件child.jsx
在子组件中打印该钩子,看父组件触发后是否会调用
import React, { Component } from 'react'export default class child extends Component {componentWillReceiveProps() {console.log('componentWillReceiveProps')}render() {return <div>{this.props.name}</div>}
}
很显然调用父组件的改名方法时,子组件的钩子也对应触发了
注意:子组件在刚进来的时候是不会调用的,只有当在父组件中更改了状态state值,才会重新触发子组件的render才会算一次调用。

该钩子还能接收参数:我们传入props

打印看效果:

-
shouldComponentUpdate(nextProps,nextState)----调用setState()时会调用,强制更新则不会触发该钩子
在渲染之前被调用,默认返回为true,在state发生变化时,都会去调用该钩子 。
不写该钩子默认返回true,写了就以你写的为主,必须要有返回值且是一个布尔值,否则会报错,返回true就正常进行,返回false时,当state更改,页面也不会更新了

可以看到每次state更新都会触发 shouldComponentUpdate钩子函数

-
componetnWillUpdate(nextProps,nextState)----------------新生命周期已替换
当组件接收到新的props和state会在渲染前调用,初始渲染不会调用该方法。
shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,不能在这使用setState,在函数返回之前不能执行任何其他更新组件的操作
点击加1

-
render()
-
componentDidUpdate(prevProps,precState,snapshot)
点击加1,在更新之后立即调用,首次渲染不会调用,之后每次重新渲染都会被调用。

方式一【调用setState触发的钩子】
从上面的打印结果我们可以看到,当调用了setState之后会触发以下三个钩子函数

注意:可以在componentDidUpdate方法调用setState,但是要包含在条件语句中,否则一直更新会造成死循环
当组件更新后,可以在此处对 DOM 进行操作。如果对更新前后的props进行了比较,可以进行网络请求。(当 props 未发生变化时,则不会执行网络请求)。
componentDidUpdate(props) {console.log('componentDidUpdate')// 典型用法(不要忘记比较 props):if (this.props.userID !== props.userID) {this.fetchData(this.props.userID)}}
方式二【调用forceUpdate触发的钩子】
当我不修改state状态只想更新一下,就不走shouldComponentUpdate了,只走以下2个钩子函数

点击强制更新可以看到触发了这两个生命周期

生命周期(旧)总结:
1.初始化阶段: 由 ReactDOM.render()触发---初次染
- constructor()
- componentWillMount()
- render()
- componentDidMount()----【常用,一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息】
2.更新阶段: 由组件内部 this.setState()或父组件重新 render 触发
- shouldComponentUpdate()
- componentWillUpdate()
- render()----【必须常用】
- componentDidUpdate()
3.卸载组件:由 ReactDOM.unmountComponentAtNode()触发
- componentWillUnmount()----【常用,一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息】
生命周期(新)

react新旧生命周期区别
新生命周期增加钩子:getDerivedStateFromProps、getSnapshotBeforeUpdate(也不常用)
在新版本中也可以用旧的生命周期,但会警告提示甚至报错:
所以对于这三个钩子:componentWillMount、componentWillUpdate、componentWillReceiveProps 需要加上 UNSAFE_ 前缀才行

总结:
新生命周期删除三个钩子:componentWillMount、componentWillUpdate、componentWillReceiveProps 这三个钩子在17.版本使用时要加上前缀UNSAFE_,即UNSAFE_componentWillMoun否则会有警告甚至报错。
这些生命周期增加使用成本,减少程序员使用。这是因为这些生命周期方法经常被误解和滥用,UNSAFE_不是指不安全,而是在未来版本中(maybe 18.xx版本中)可能出现bug,特别是异步渲染中。实际很少使用这三个钩子,基本不用的。所以了解即可。
挂载时的生命周期
-
constructor --上面已讲
-
getDerivedStateFromProps --详细讲解
这个生命周期的意思就是从props中获取state,可以说是太简单易懂了。可以说,这个生命周期的功能实际上就是将传入的props映射到state上面。
由于16.4的修改,这个函数会在每次re-rendering之前被调用,这意味着什么呢?
意味着即使你的props没有任何变化,而是父state发生了变化,导致子组件发生了re-render,这个生命周期函数依然会被调用。看似一个非常小的修改,却可能会导致很多隐含的问题。
这个生命周期函数是为了替代componentWillReceiveProps存在的,所以在你需要使用componentWillReceiveProps的时候,就可以考虑使用getDerivedStateFromProps来进行替代了。
当我们直接去使用的会报错:

报错内容的意思就是:该生命周期不能作为一个实例方法去调用,应该将它声明为静态方法,需要加上static关键字

解决:

可以打印了,但仍然报错,意思是:该生命周期必须要有返回值,可以是两种情况,一种是状态对象,或者是null,但没有返回值不行。
我们返回一个状态对象,试一下:

看页面效果,当返回一个状态对象后,我们再去通过点我加1改变count值,值是不会被改变的

说明当我们返回一个状态对象后,会影响状态更新,并且不会以初始化为主,就会以它返回的为主,并且以后也都改不了了。
那我们在这里传入一个count

在该钩子进行接收,并返回props

那么页面就会优先使用该状态,且不可更改。 此时就验证了官网所说,使用了该生命周期后,state的值在任何时候都取决于props

这就体现了该生命周期的含义,从props那得到一个衍生的状态。
需要注意的是,它可以接收2个参数,一个是props,一个是state,如果props传入的内容不需要影响到你的state,那么就需要返回一个null,这个返回值是必须的,所以尽量将其写到函数的末尾。
static getDerivedStateFromProps(props, state) {console.log(props, state)const { count } = propsif (count !== state.count) {return {count,}}return null}
使用场景就是:
(1)若state的值在任何时候都取决于props,可以使用,也不是必须
(2)可以通过对比props中某个属性的值,和state中的值,在不同的情况下使用不同的状态。
总之:也不太建议使用,派生状态会导致代码冗余,并使组件难以维护,了解即可
-
render --上面已讲
-
componentDidMount --上面已讲
渲染时的生命周期
-
getDerivedStateProps --上面已讲
-
shouldComponentUpdate -- 控制组件更新的开关,上面已讲
-
render --上面已讲
-
getSnapshotBeforeUpdate -- 详细讲解
当我们点击加1,进行渲染的时候,该生命周期就会报错

此时上面的警告就是需要一个返回值,返回null或者一个snapshot(快照值--字符串、数组、对象、函数都可作为快照值)
因此我们可以在更新前获取快照,然后再组件更新完毕的时候可以获取快照:
使用场景:例如在列表没更新前我们想获取当前10条数据的高度,这时候就可以通过快照保存,在更新之后变为11条,照样可以拿到之前的列表高度。
// 在更新之前获取快照getSnapshotBeforeUpdate() {console.log('getSnapshotBeforeUpdate')let { count } = this.statereturn 'suosuo'}// 组件更新完毕的钩子componentDidUpdate(prePops, preState, snapshotValue) {console.log('componentDidUpdate', prePops, preState, snapshotValue)}
使用场景 :例如 列表内容定时自动加一条,当滚动到某个位置时,停留在此位置
原理:我们就可以通过getSnapshotBeforeUpdate生命周期记录当前
import React, { Component } from 'react'
import './demo.css'export default class demo extends Component {state = { newsArr: [] }componentDidMount() {setInterval(() => {const { newsArr } = this.stateconst news = '哈哈' + (newsArr.length + 1)this.setState({newsArr: [news, ...newsArr],})}, 1000)}//保存更新列表前的列表的高度getSnapshotBeforeUpdate() {return this.refs.list.scrollHeight}componentDidUpdate(preProps, preState, height) {//此时滚动条的滚动的位置就加等于当前列表高度减去保存之前列表高度//this.refs.list.scrollHeight - height其实就是一条消息的高度//因此要想一直停留在此处,得用+=this.refs.list.scrollTop += this.refs.list.scrollHeight - height}render() {return (<div className="list" ref="list">{this.state.newsArr.map((n, i) => {return (<div className="news" key={i}>{n}</div>)})}</div>)}
}
效果:此时就可以看到,我们悬浮到哪条信息的位置,就会停留在哪,即便数据仍在添加,也不影响

-
componentDidUpdate--上面已讲
卸载时的生命周期
-
componentWillUnmount --同旧的一样,不讲喽
生命周期(新)总结:
1、初始化阶段: 由ReactDOM.render()触发---初次渲染
- constructor()
- getDerivedStateFromProps
- render()
- componentDidMount() --常用
2,更新阶段: 由组件内部this.setSate()或父组件重新render触发
- getDerivedStateFromProps
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate
- componentDidUpdate()
3,卸载组件: 由ReactDOM.unmountComponentAtNode()触发
- componentWillUnmount() --常用
重要的钩子
- render:初始化渲染或更新渲染调用
- componentDidMount:开启监听,发送ajax请求
- componentWillUnmount:做一些收尾工作,如:清理定时器
即将废弃的子
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
现在使用会出现警告,下一个大版本需要加上 UNSAFE_前缀才能使用,以后可能会被彻底
废弃,不建议使用。
本文主要参考链接:
react生命周期详细介绍_小薯片子的博客-CSDN博客
React新生命周期--getDerivedStateFromProps - 简书
相关文章:
【react全家桶学习】react的 (新/旧) 生命周期(重点)
目录 生命周期(旧) 挂载时的生命周期 constructor(props) componentWillMount()-------------新生命周期已替换 render() componentDidMount()--- 组件…...
Gradio私网和公网的使用
Gradio私网问题 如果部署的服务器只有私有地址,那么无法直接从外部网络中的其他计算机访问该服务器和其中运行的 Gradio 应用程序。在这种情况下,你可以考虑使用端口转发技术,将服务器的私有地址映射到一定的公开地址上,从而可以…...
ant design vue 配置菜单外部打开
实现如下 菜单配置 前端项目地址:http://localhost:3000 菜单路径:dataCenter/HealthData 打开方式:外部 在项目中src-->config-->router.config.js文件 将需要再外部打开的菜单地址进行如下配置 菜单地址:/dataCenter/Hea…...
YOLOv5/v7 添加注意力机制,30多种模块分析⑦,CCN模块,GAMAttention模块
目录 一、注意力机制介绍1、什么是注意力机制?2、注意力机制的分类3、注意力机制的核心 二、CCN模块1、CCN模块的原理2、实验结果3、应用示例 三、GAMAttention模块1、GAMAttention模块的原理2、实验结果3、应用示例 大家好,我是哪吒。 🏆本…...
IDEA下Logback.xml自动提示功能配置
首先打开logback的配置文件,在configuration标签中加入xsd的配置 <configuration xmlns"http://ch.qos.logback/xml/ns/logback"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://ch.qos.logback/xml…...
CUDA编程模型系列八(原子操作 / 规约 / 向量元素求和)
本系列视频目的是帮助开发者们一步步地学会利用CUDA编程模型加速GPU应用, 我们的口号是: 让GPU飞起来 本期我介绍了cuda 当中规约算法的一种情况, 也是小何尚职业生涯中的第一道面试题, 计算数组中所有元素的和. CUDA编程模型系列八(原子操作 / 规约 / 向量元素求和) #include…...
go语言系列基础教程总结(4)
1、goroutine和channel 每执行一次go func()就创建一个 goroutine,包含要执行的函数和上下文信息。 goroutine 是Go程序并发的执行体,channel是它们之间的沟通连接通道。 var ch1 chan int. //声明一个整型的通道 2、channel 常用操作 //定义一个…...
网络基础一:网络协议初识与网络传输基本流程
目录 网络协议认识“协议”网络协议初识协议分层OSI七层模型(理论模型)TCP/IP五层(或四层)模型(工程实现模型) 网络中的地址管理MAC地址IP地址 网络传输基本流程路由的本质 数据包封装和分用网络协议需要解决的问题 网络协议 计算…...
Mysql找出执行慢的SQL【慢查询日志使用与分析】
分析慢SQL的步骤 慢查询的开启并捕获:开启慢查询日志,设置阈值,比如超过5秒钟的就是慢SQL,至少跑1天,看看生产的慢SQL情况,并将它抓取出来explain 慢SQL分析show Profile。(比explain还要详细…...
设计模式3:单例模式:JMM与volatile和synchronized的关系
本文目录 JMM简介Java 内部内存模型(The Internal Java Memory Model)硬件内存架构(Hardware Memory Architecture)弥合 Java 内存模型和硬件内存架构之间的差距(Bridging The Gap Between The Java Memory Model And The Hardware Memory Architecture)1.共享对象的可见性2.竞…...
一个简单的OPC UA/ModbusTCP 网关(Python)
使用我前面几篇博文的内容,能够使用Python编写一个最简单的OPC UA /ModbusTCP网关。 从这个程序可以看出: 应用OPC UA 并不难,现在我们就可以应用到工程应用中,甚至DIY项目也可以。不必采用复杂的工具软件。使用Python 来构建工…...
线性代数行列式的几何含义
行列式可以看做是一系列列向量的排列,并且每个列向量的分量可以理解为其对应标准正交基下的坐标。 行列式有非常直观的几何意义,例如: 二维行列式按列向量排列依次是 a \mathbf{a} a和 b \mathbf{b} b,可以表示 a \mathbf{a} a和…...
python用flask将视频显示在网页上
注意我们的return返回值必须是以下之一,否则会报错 from flask import Flask, render_template, Response import cv2app Flask(__name__)app.route(/) def index():return render_template(index.html)def gen(camera):while True:success, image camera.read(…...
【数据挖掘】时间序列教程【一】
第一章 说明 对于时间序列的研究,可以追溯到19世纪末和20世纪初。当时,许多学者开始对时间相关的经济和社会现象进行研究,尝试发现其规律和趋势。其中最早的时间序列研究可以追溯到法国经济学家易贝尔(Maurice Allais)…...
优化索引粒度参数提升ClickHouse查询性能
当对高基数列进行过滤查询时,总是希望尽可能跳过更多的行。否则需要处理更多数据、需要更多资源。ClickHouse缺省在MergeTree表读取8192行数据块,但我们可以在创建表时调整该index_granularity 参数。本文通过示例说明如何调整该参数优化查询性能。 inde…...
selenium\webdriver\remote\errorhandler.py:242: SessionNotCreatedException问题解决
报错信息: raise exception_class(message, screen, stacktrace) E selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 112 E Current browser versi…...
MySQL 备份与恢复
MySQL 备份与恢复 一、数据库备份的分类1.1 数据备份的重要性1.2 数据库备份的分类1.2.1 从物理与逻辑的角度,分为物理备份和逻辑备份1.2.2 从数据库的备份策略角度,分为完全备份,差异备份和增量备份1.2.3 常见的备份方法 二、MySQL完全备份与…...
js中改变this指向的三种方式
js中改变this指向的三种方式 1、call方法2、apply方法3、bind方法 1、call方法 使用 call 方法调用函数,同时指定函数中 this 的值,使用方法如下代码所示: <script>const obj {uname: 刘德华}function fn(x, y) {console.log(this) …...
小程序中如何进行数据传递和通信
103. 小程序中如何进行数据传递和通信? 1. 使用页面参数传递数据: 在小程序中,可以通过页面参数来传递数据。当跳转到一个新页面时,可以将需要传递的数据作为参数传入,然后在目标页面的onLoad函数中获取参数。 示例…...
Vue3项目中引入ElementUI使用详解
目录 Vue3项目中引入 ElementUI1.安装2.引入2.1 全局引入2.2 按需引入viteWebpack 3.使用 Vue3项目中引入 ElementUI ElementUI是一个强大的PC端UI组件框架,它不依赖于vue,但是却是当前和vue配合做项目开发的一个比较好的ui框架,其包含了布局…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...
深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...
Qwen系列之Qwen3解读:最强开源模型的细节拆解
文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...
以太网PHY布局布线指南
1. 简介 对于以太网布局布线遵循以下准则很重要,因为这将有助于减少信号发射,最大程度地减少噪声,确保器件作用,最大程度地减少泄漏并提高信号质量。 2. PHY设计准则 2.1 DRC错误检查 首先检查DRC规则是否设置正确,然…...
Linux实现线程同步的方式有哪些?
什么是线程同步? 想象一下超市收银台:如果所有顾客(线程)同时挤向同一个收银台(共享资源),场面会一片混乱。线程同步就是给顾客们发"排队号码牌",确保: 有序访…...
【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理
这篇学习笔记是Spring系列笔记的第7篇,该笔记是笔者在学习黑马程序员SSM框架教程课程期间的笔记,供自己和他人参考。 Spring学习笔记目录 笔记1:【SSM】Spring基础: IoC配置学习笔记-CSDN博客 对应黑马课程P1~P20的内容。 笔记2…...
