【react全家桶】生命周期

news2024/11/17 9:27:42

文章目录

  • 04 【生命周期】
    • 1.简介
    • 2.初始化阶段
      • 2.1 constructor
      • 2.2 componentWillMount(即将废弃)
      • 2.3 static getDerivedStateFromProps(新钩子)
      • 2.4 render
      • 2.5 componentDidMount
      • 2.6 初始化阶段总结
    • 3.更新阶段
      • 3.1 componentWillReceiveProps (即将废弃)
      • 3.2 shouldComponentUpdate
      • 3.3 componentWillUpdate (即将废弃)
      • 3.4 getSnapshotBeforeUpdate(新钩子)
      • 3.5 componentDidUpdate
      • 3.6 getSnapshotBeforeUpdate使用场景
    • 4.卸载组件
      • 4.1 componentWillUnmount

04 【生命周期】

1.简介

组件从创建到死亡,会经过一些特定的阶段

React组件中包含一系列钩子函数{生命周期回调函数},会在特定的时刻调用

我们在定义组件的时候,会在特定的声明周期回调函数中,做特定的工作

在 React 中为我们提供了一些生命周期钩子函数,让我们能在 React 执行的重要阶段,在钩子函数中做一些事情。那么在 React 的生命周期中,有哪些钩子函数呢,我们来总结一下

react生命周期(旧)

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

react生命周期(旧)

在最新的react版本中,有些生命周期钩子被抛弃了,具体函数如下:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

这些生命周期方法经常被误解和滥用;此外,我们预计,在异步渲染中,它们潜在的误用问题可能更大。我们将在即将发布的版本中为这些生命周期添加 “UNSAFE_” 前缀。(这里的 “unsafe” 不是指安全性,而是表示使用这些生命周期的代码在 React 的未来版本中更有可能出现 bug,尤其是在启用异步渲染之后。)

由此可见,新版本中并不推荐持有这三个函数,取而代之的是带有UNSAFE_ 前缀的三个函数,比如: UNSAFE_ componentWillMount。即便如此,其实React官方还是不推荐大家去使用,在以后版本中有可能会去除这几个函数。

react生命周期(新)

1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
                1.	constructor()
                2.	getDerivedStateFromProps 
                3.	render()
                4.	componentDidMount() =====> 常用
                	一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
                1.	getDerivedStateFromProps
                2.	shouldComponentUpdate()
                3.	render()
                4.	getSnapshotBeforeUpdate
                5.	componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
                1.	componentWillUnmount()  =====> 常用
                	一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

image-20221023222949399

2.初始化阶段

在组件实例被创建并插入到dom中时,生命周期调用顺序如下

旧生命周期:

  1. constructor(props)
  2. componentWillMount()-------------可以用但是不建议使用
  3. render()
  4. componentDidMount()

新生命周期:

  1. constructor(props)
  2. static getDerivedStateFromProps(props,state)–替代了componentWillReceiveProps
  3. render()
  4. componentDidMount()

2.1 constructor

数据的初始化。

接收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)。

现在我们通常不会使用 constructor 属性,而是改用类加箭头函数的方法,来替代 constructor

例如,我们可以这样初始化 state

state = {
	count: 0
};

2.2 componentWillMount(即将废弃)

该方法只在挂载的时候调用一次,表示组件将要被挂载,并且在 render 方法之前调用。

如果存在 getDerivedStateFromPropsgetSnapshotBeforeUpdate 就不会执行生命周期componentWillMount

​ 在服务端渲染唯一会调用的函数,代表已经初始化数据但是没有渲染dom,因此在此方法中同步调用 setState() 不会触发额外渲染。

这个方法在 React 18版本中将要被废弃,官方解释是在 React 异步机制下,如果滥用这个钩子可能会有 Bug

2.3 static getDerivedStateFromProps(新钩子)

从props获取state。

替代了componentWillReceiveProps,此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props。

这个是 React 新版本中新增的2个钩子之一,据说很少用。

  1. 首先,该函数会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用;

  2. 该函数必须是静态的;

  3. 给组件传递的数据(props)以及组件状态(state),会作为参数到这个函数中;

  4. 该函数也必须有返回值,返回一个Null或者state对象。因为初始化和后续更新都会执行这个方法,因此在这个方法返回state对象,就相当于将原来的state进行了覆盖,所以倒是修改状态不起作用。

注意:state 的值在任何时候都取决于传入的 props ,不会再改变

如下

static getDerivedStateFromProps(props, state) {
    return null											
}
ReactDOM.render(<Count count="109"/>,document.querySelector('.test'))

count 的值不会改变,一直是 109

React的生命周期 - 简书

老版本中的componentWillReceiveProps()方法判断前后两个 props 是否相同,如果不同再将新的 props 更新到相应的 state 上去。这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,另一方面也会增加组件的重绘次数。

这两者最大的不同就是:
在 componentWillReceiveProps 中,我们一般会做以下两件事,一是根据 props 来更新 state,二是触发一些回调,如动画或页面跳转等。

  1. 在老版本的 React 中,这两件事我们都需要在 componentWillReceiveProps 中去做。
  2. 而在新版本中,官方将更新 state 与触发回调重新分配到了 getDerivedStateFromProps 与 componentDidUpdate 中,使得组件整体的更新逻辑更为清晰。而且在 getDerivedStateFromProps 中还禁止了组件去访问 this.props,强制让开发者去比较 nextProps 与 prevState 中的值,以确保当开发者用到 getDerivedStateFromProps 这个生命周期函数时,就是在根据当前的 props 来更新组件的 state,而不是去做其他一些让组件自身状态变得更加不可预测的事情。

2.4 render

class组件中唯一必须实现的方法。

render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。

注意:避免在 render 中使用 setState ,否则会死循环

当render被调用时,他会检查this.props.和this.state的变化并返回以下类型之一:

  1. 通过jsx创建的react元素
  2. 数组或者fragments:使得render可以返回多个元素
  3. Portals:可以渲染子节点到不同的dom树上
  4. 字符串或数值类型:他们在dom中会被渲染为文本节点
  5. 布尔类型或者null:什么都不渲染

2.5 componentDidMount

在组件挂在后(插入到dom树中)后立即调用

componentDidMount 的执行意味着初始化挂载操作已经基本完成,它主要用于组件挂载完成后做某些操作

这个挂载完成指的是:组件插入 DOM tree

​ 可以在这里调用Ajax请求,返回的数据可以通过setState使组件重新渲染,或者添加订阅,但是要在conponentWillUnmount中取消订阅

2.6 初始化阶段总结

执行顺序 constructor -> getDerivedStateFromProps 或者 componentWillMount -> render -> componentDidMount

image-20221023223048451

3.更新阶段

当组件的 props 或 state 发生变化时会触发更新。

旧生命周期:

  1. componentWillReceiveProps (nextProps)------------------可以用但是不建议使用

  2. shouldComponentUpdate(nextProps,nextState)

  3. componetnWillUpdate(nextProps,nextState)----------------可以用但是不建议使用

  4. render()

  5. componentDidUpdate(prevProps,precState,snapshot)

新生命周期:

  1. static getDerivedStateFromProps(nextProps, prevState)
  2. shouldComponentUpdate(nextProps,nextState)
  3. render()
  4. getSnapshotBeforeUpdate(prevProps,prevState)
  5. componentDidUpdate(prevProps,precState,snapshot)

3.1 componentWillReceiveProps (即将废弃)

在已挂载的组件接收新的props之前调用。

通过对比nextProps和this.props,将nextProps的state为当前组件的state,从而重新渲染组件,可以在此方法中使用this.setState改变state。

componentWillReceiveProps (nextProps) {
    nextProps.openNotice !== this.props.openNotice&&this.setState({
        openNotice:nextProps.openNotice
    }() => {
      console.log(this.state.openNotice:nextProps)
      //将state更新为nextProps,在setState的第二个参数(回调)可以打         印出新的state
    })
}

请注意,如果父组件导致组件重新渲染,即使 props 没有更改,也会调用此方法。如果只想处理更改,请确保进行当前值与变更值的比较。

React 不会针对初始 props 调用 UNSAFE_componentWillReceiveProps()。组件只会在组件的 props 更新时调用此方法。调用 this.setState() 通常不会触发该生命周期。

3.2 shouldComponentUpdate

在渲染之前被调用,默认返回为true。

​ 返回值是判断组件的输出是否受当前state或props更改的影响,默认每次state发生变化都重新渲染,首次渲染或使用forceUpdate(使用this.forceUpdate())时不被调用。

他主要用于性能优化,会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。不建议深层比较,会影响性能。如果返回false,则不会调用componentWillUpdate、render和componentDidUpdate

  • 唯一用于控制组件重新渲染的生命周期,由于在react中,setState以后,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新,但是不建议,建议使用 PureComponent
  • 因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断

3.3 componentWillUpdate (即将废弃)

当组件接收到新的props和state会在渲染前调用,初始渲染不会调用该方法。

​ shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,不能在这使用setState,在函数返回之前不能执行任何其他更新组件的操作

此方法可以替换为 componentDidUpdate()。如果你在此方法中读取 DOM 信息(例如,为了保存滚动位置),则可以将此逻辑移至 getSnapshotBeforeUpdate() 中。

3.4 getSnapshotBeforeUpdate(新钩子)

在最近一次的渲染输出之前被提交之前调用,也就是即将挂载时调用,替换componetnWillUpdate。

相当于淘宝购物的快照,会保留下单前的商品内容,在 React 中就相当于是 即将更新前的状态

它可以使组件在 DOM 真正更新之前捕获一些信息(例如滚动位置),此生命周期返回的任何值都会作为参数传递给 componentDidUpdate()。如不需要传递任何值,那么请返回 null

和componentWillUpdate的区别

  • 在 React 开启异步渲染模式后,在 render 阶段读取到的 DOM 元素状态并不总是和 commit 阶段相同,这就导致在componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
  • getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。

3.5 componentDidUpdate

组件在更新完毕后会立即被调用,首次渲染不会调用

可以在该方法调用setState,但是要包含在条件语句中,否则一直更新会造成死循环。

当组件更新后,可以在此处对 DOM 进行操作。如果对更新前后的props进行了比较,可以进行网络请求。(当 props 未发生变化时,则不会执行网络请求)。

componentDidUpdate(prevProps,prevState,snapshotValue) {
  // 典型用法(不要忘记比较 props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

如果组件实现了 getSnapshotBeforeUpdate() 生命周期(不常用),则它的返回值将作为 componentDidUpdate() 的第三个参数 “snapshotValue” 参数传递。否则此参数将为 undefined。如果返回false就不会调用这个函数。

3.6 getSnapshotBeforeUpdate使用场景

在一个区域内,定时的输出以行话,如果内容大小超过了区域大小,就出现滚动条,但是内容不进行移动

BeforeGender

如上面的动图:区域内部的内容展现没有变化,但是可以看见滚动条在变化,也就是说上面依旧有内容在输出,只不过不在这个区域内部展现。

1.首先我们先实现定时输出内容

我们可以使用state状态,改变新闻后面的值,但是为了同时显示这些内容,我们应该为state的属性定义一个数组。并在创建组件之后开启一个定时器,不断的进行更新state。更新渲染组件

 class New extends React.Component{

        state = {num:[]};

        //在组件创建之后,开启一个定时任务
        componentDidMount(){
            setInterval(()=>{
                let {num} = this.state;
                const news = (num.length+1);
                this.setState({num:[news,...num]});
            },2000);
        }

        render(){
            return (
                <div ref = "list" className = "list">{
                    this.state.num.map((n,index)=>{
                    return <div className="news" key={index} >新闻{n}</div>
                    })
                }</div>
            )
        }
  }
  ReactDOM.render(<New />,document.getElementById("div"));

2.接下来就是控制滚动条了

我们在组件渲染到DOM之前获取组件的高度,然后用组件渲染之后的高度减去之前的高度就是一条新的内容的高度,这样在不断的累加到滚动条位置上。

getSnapshotBeforeUpdate(){
	return this.refs.list.scrollHeight;
}

componentDidUpdate(preProps,preState,height){
	this.refs.list.scrollTop += (this.refs.list.scrollHeight - height);
}

这样就实现了这个功能。

4.卸载组件

当组件从 DOM中移除时会调用如下方法

4.1 componentWillUnmount

在组件卸载和销毁之前调用

使用这样的方式去卸载ReactDOM.unmountComponentAtNode(document.getElementById('test'))

​ 在这执行必要的清理操作,例如,清除timer(setTimeout,setInterval),取消网络请求,或者取消在componentDidMount的订阅,移除所有监听

有时候我们会碰到这个warning:

Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a   no-op. Please check the code for the undefined component.

原因:因为你在组件中的ajax请求返回setState,而你组件销毁的时候,请求还未完成,因此会报warning

解决方法:

componentDidMount() {
    this.isMount === true
    axios.post().then((res) => {
    this.isMount && this.setState({   // 增加条件ismount为true时
      aaa:res
    })
})
}
componentWillUnmount() {
    this.isMount === false
}

componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

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

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

相关文章

2023最新版本RabbitMQ的持久化和简单使用

上节讲了 RabbitMQ下载安装教程 &#xff0c; 本节主要介绍RabbitMQ的持久化和简单使用。 一、RabbitMQ消息持久化 当处理一个比较耗时得任务的时候&#xff0c;也许想知道消费者&#xff08;consumers&#xff09;是否运行到一半就挂掉。在当前的代码中&#xff0c;当RabbitM…

如何在本地跑FuzzBench的实验

概述 FuzzBench是谷歌做的一个评估模糊测试的benchmark&#xff0c;主要目的是为了评测覆盖率导向模糊测试工具能达到多少覆盖率&#xff0c;能够发现多少漏洞。本文主要介绍如何在本地运行fuzzbench的实验。当然也可以用谷歌的云服务来跑&#xff0c;具体教程在这&#xff1a…

计算机底层:BDC码

计算机底层&#xff1a;BDC码 BDC码的作用&#xff1a; 人类喜欢十进制&#xff0c;而机器适合二进制&#xff0c;因此当机器要翻译二进制给人看时&#xff0c;就会进行二进制和十进制的转换&#xff0c;而常规的转换法&#xff08;k*位权&#xff09;太麻烦。因此就出现了不同…

基本类型、包装类型、引用类型、String等作为实参传递后值会不会改变?

看了半天帖子&#xff0c;讲得乱七八糟&#xff0c;坑死了 [1] 先说结论 基本类型、包装类型、String类型作为参数传递之后&#xff0c;在方法里面修改他们的值&#xff0c;原值不会改变&#xff01;引用类型不一定&#xff0c;要看是怎么修改它的。 [2] 为什么基本类型、包装类…

程序设计语言-软件设计(二十一)

数据结构与算法&#xff08;二十&#xff09;快速排序、堆排序(四)https://blog.csdn.net/ke1ying/article/details/129269655 这篇主要讲的是 编译与解释、文法、正规式、有限自动机、表达式、传值与传址、多种程序语言特点。 编译的过程 解释型 和 编译型 编译型过程&#…

【IDEA】IDEA使用有道翻译引擎—详细配置步骤

目录 前言 步骤一&#xff1a;下载翻译工具Translate 步骤二&#xff1a;注册登录有道云平台 步骤三&#xff1a;配置有道翻译 前言 2022年10月 谷歌翻译已经不在中国了&#xff0c;所以IDEA配置谷歌翻译会出错。 步骤一&#xff1a;下载翻译工具Translate 打开idea设置set…

c语言经典例题-选择结构程序设计进阶

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 快递费用计算&#xff1a; 题目&#xff1a; 代码思路&#xff1a; 代码表示&#xff1a; 计算一元二…

Java奠基】数组的讲解与使用

目录 数组概述 数组的定义与初始化 数值遍历 数组的常见操作 数组内存图 数组概述 数组是一种容器&#xff0c;可以用来存储同种数据类型的多个值&#xff0c;数组容器在存储数据的时候&#xff0c;需要结合隐式转换考虑。例如&#xff1a;int类型的数组容器不能存放取值…

191、【动态规划】AcWing ——AcWing 900. 整数划分:完全背包解法+加减1解法(C++版本)

题目描述 参考文章&#xff1a;900. 整数划分 解题思路 因为本题中规定了数字从大到小&#xff0c;其实也就是不论是1 2 1 4&#xff0c;还是2 1 1 4&#xff0c;都会被看作是2 1 1 4这一种情况&#xff0c;因此本题是在遍历中不考虑结果顺序。 背包问题中只需考虑…

mysql一条语句的写入原理

mysql写入原理 我们知道在mysql数据库最核心的大脑就是执行引擎&#xff1b; 其中的默认引擎Innodb在可靠执行和性能中做出来平衡&#xff1b; innodb支持在事务控制、读写效率&#xff0c;多用户并发&#xff0c;索引搜索方面都表现不俗&#xff1b; innodb如何进行数据写入…

MYSQL性能分析,Explain,Show Profile

文章目录一、MYSQL常见瓶颈二、ExplainExplain是什么三、Show Profile四、慢查询日志和全局查询日志一、MYSQL常见瓶颈 CPU&#xff1a; CPU饱和IO&#xff1a;磁盘IO速度过慢。服务器的硬件性能瓶颈。 二、Explain Explain是什么 使用explain关键字可以模拟优化器执行sql查…

YApi分析从NoSQL注入到RCE远程命令执行.md

0x00 前提 这个是前几个月的漏洞&#xff0c;之前爆出来发现没人分析就看了一下&#xff0c;也写了一片 Nosql注入的文章&#xff0c;最近生病在家&#xff0c;把这个写一半的完善一下发出来吧。 0x01 介绍 YApi是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台…

【C++】命名空间

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录前言一、命名空间产生的背景二、命名空…

【一天时间|简历模板】世界上最好的前端简历

一天时间系列文章是博主精心整理的面试热点问题和难点问题&#xff0c;吸收了大量的技术博客与面试文章&#xff0c;总结多年的面试经历&#xff0c;带你快速并高效地审视前端面试知识。直击技术痛点&#xff0c;主动出击&#xff0c;精密打击&#xff0c;这才是面试拿到高薪的…

网络基础知识(IP地址、TCP协议/IP协议、UDP协议、三次握手,四次挥手的过程、端口等的概念)

TCP/IP 协议 首先给大家说明的是&#xff0c;TCP/IP 协议它其实是一个协议族&#xff0c;包含了众多的协议&#xff0c;譬如应用层协议 HTTP、FTP、MQTT…以及传输层协议 TCP、UDP 等这些都属于 TCP/IP 协议。 所以&#xff0c;我们一般说 TCP/IP 协议&#xff0c;它不是指某…

unity-与js交互

title: unity-与js交互 categories: Unity3d tags: [unity, js, web, h5] date: 2023-03-05 00:09:52 comments: false mathjax: true toc: true unity-与js交互 前篇 官方 WebGL&#xff1a;与浏览器脚本交互 - https://docs.unity3d.com/cn/2021.1/Manual/webgl-interacting…

JavaWeb--JSP

JSP1 JSP 概述2 JSP 快速入门2.1 搭建环境2.2 导入 JSP 依赖2.3 创建 jsp 页面2.4 编写代码2.5 测试3 JSP 原理4 JSP 脚本4.1 JSP 脚本分类4.2 案例4.2.1 需求4.2.2 实现4.2.3 成品代码4.2.4 测试4.3 JSP 缺点5 EL 表达式5.1 概述5.2 代码演示5.3 域对象6 JSTL标签6.1 概述6.2 …

Android应用启动优化笔记整理

应用启动相关流程与优化 应用启动主要涉及SystemServer进程 和 app进程。 SystemServer进程负责app进程创建和管理、窗口的创建和管理&#xff08;StartingWindow 和 AppWindow&#xff09;、应用的启动流程调度等。 App进程被创建后&#xff0c;进行一系列进程初始化、组件初…

【LinkedList】| 深度剥析Java SE 源码合集Ⅰ

目录一. &#x1f981; LinkedList介绍二. &#x1f981; 结构以及对应方法分析2.1 结构组成2.1.1 节点类2.1.2 成员变量2.2 方法实现2.2.1 添加add(E e)方法2.2.2 头尾添加元素Ⅰ addFirst(E e)Ⅱ addLast(E e)2.2.3 查找get(int index)方法2.2.4 删除remove()方法三. &#x…

【云原生】整合K8s + SpringCloudK8s + gRpc + RocketMQ + Istio + Envoy

背景本文把前面的代码整理一遍&#xff0c;不仅仅是demo层面&#xff0c;而是考虑到放进生产中使用&#xff0c;且尽可能用高版本&#xff0c;关于这块技术&#xff0c;网上的文章真是一言难尽&#xff0c;要么就是个概念&#xff0c;要么就是把官网的demo拿过来跑一遍&#xf…