【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框架,其包含了布局…...

计算机启动
按下主机上的 power 键后,第一个运行的软件是 BIOS,BIOS 全称叫 Base Input & Output System,即基本输入输出系统。 (8086的1MB内存) 地址 0~0x9FFFF 处是 DRAM,顶部的 0xF0000~0xFFFFF&am…...

Unity学习笔记--EventSystem事件系统在使用上需要注意的地方(很基础,但是很多人会忘记!!!)
目录 前言代码Unity 场景配置运行报错分析解决办法拓展(预告) 前言 之前有写过一篇关于事件系统实现以及使用的文章 Unity学习笔记–C#事件系统的实现与应用 最近在使用的时候遇到了一些问题,所以在此记录下,也为看到这篇文章的人…...

高手必备:JVM调优的常用命令和参数一网打尽!
大家好,我是小米!在今天的技术分享中,我将和大家一起探讨JVM调优中的常用命令和参数。作为一名热爱技术的小伙伴,希望通过本篇文章的分享,能够帮助大家更好地理解和掌握JVM调优的方法和技巧。 JVM的结构 首先&#x…...

Uniapp 开发 ①(快速上手)
作者 : SYFStrive 博客首页 : HomePage 📜: UNIAPP开发 📌:个人社区(欢迎大佬们加入) 👉:社区链接🔗 📌:觉得文章不错可以点点关注 Ǵ…...

【数据库原理与实践】知识点归纳(下)
第6章 规范化理论 一、关系模式设计中存在的问题 关系、关系模式、关系数据库、关系数据库的模式 关系模式看作三元组:R < U,F >,当且仅当U上的一个关系r满足F时,r称为关系模式R < U,F >的一个关系 第一范式(1NF&…...

代码随想录day34
1005.K次取反后最大化的数组和 本题主要是想到排序的时候要按绝对值大小排序。 class Solution { static bool cmp(int a,int b){return abs(a)>abs(b); } public:int largestSumAfterKNegations(vector<int>& nums, int k) {sort(nums.begin(),nums.end(),cmp);…...

CSS知识点汇总(八)--Flexbox
1. flexbox(弹性盒布局模型)是什么,适用什么场景? 1. flexbox(弹性盒布局模型)是什么 Flexible Box 简称 flex,意为”弹性布局”,可以简便、完整、响应式地实现各种页面布局。采用…...

ASCII、Unicode、UTF-8、GBK
入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删。 目录 一、定义 1、ASCII 2、Unicode 3、UTF-8 4、GB2312 5、GBK 6、\u和\x 二、相互转化 1、str 与 ASCII 2、str与utf-…...

【安全】使用docker安装Nessus
目录 一、准备docker环境服务器(略) 二、安装 2.1 搜索镜像 2.2 拉取镜像 2.3 启动镜像 三、离线更新插件 3.1 获取challenge 3.2 官方注册获取激活码 3.3 使用challenge码和激活码获取插件下载地址 3.4 下载的插件以及许可协议复制到容器内 四…...

【Hadoop综合实践】手机卖场大数据综合项目分析
🚀 本文章实现了基于MapReduce的手机浏览日志分析 🚀 文章简介:主要包含了数据生成部分,数据处理部分,数据存储部分与数据可视化部分 🚀 【本文仅供参考!!非唯一答案】其中需求实现的…...