【react从入门到精通】深入理解react生命周期这一篇就够了

news2025/1/12 23:15:16

文章目录

  • 前言
  • React的生命周期是什么
  • React v16.0前的生命周期
    • 组件初始化(initialization)阶段
    • 组件挂载(Mounting)阶段
    • 组件更新(update)阶段
    • 组件销毁阶段
  • React v16.4 的生命周期
  • 总结
  • 写在最后

在这里插入图片描述

前言

在上一篇文章《react入门这一篇就够了》中我们已经掌握了React的基本知识。通过使用React组件我们对页面进行渲染;通过使用React事件处理函数对用户操作进行响应;通过React状态的改变对页面进行刷新。本文中我们将深入的了解React的生命周期,以及在这些生命周期可以做些什么。

React的生命周期是什么

React的生命周期表示了React组件从构建到注销所经历的一系列过程。React生命周期有各自执行的顺序和作用。主要包括的生命周期为:组件的初始化阶段,组件的挂载阶段,组件的更新阶段以及组件的销毁阶段。

React v16.0前的生命周期

有些团队不一定会升到16版本,所以16前的生命周期还是很有必要掌握的。

组件初始化(initialization)阶段

也就是以下代码中类的构造方法( constructor() ),Test类继承了react Component这个基类,也就继承这个react的基类,才能有render(),生命周期等方法可以使用,这也说明为什么函数组件不能使用这些方法的原因。

super(props)用来调用基类的构造方法( constructor() ), 也将父组件的props注入给子组件,供子组件读取(组件中props只读不可变,state可变)。

而constructor()用来做一些组件的初始化工作,如定义this.state的初始内容。

import React, { Component } from 'react';

class Test extends Component {
  constructor(props) {
    super(props);
  }
}

组件挂载(Mounting)阶段

此阶段分为componentWillMount,render,componentDidMount三个时期。

componentWillMount:
在组件挂载到DOM前调用,且只会被调用一次,在这边调用this.setState不会引起组件重新渲染,也可以把写在这边的内容提前到constructor()中,所以项目中很少用。

render:
根据组件的props和state(无论两者的重传递和重赋值,无论值是否有变化,都可以引起组件重新render) ,return 一个React元素(描述组件,即UI),不负责组件实际渲染工作,之后由React自身根据此元素去渲染出页面DOM。render是纯函数(Pure function:函数的返回结果只依赖于它的参数;函数执行过程里面没有副作用),不能在里面执行this.setState,会有改变组件状态的副作用。

componentDidMount:
组件挂载到DOM后调用,且只会被调用一次

简言之,componentWillMount函数在我们Render方法前触发属于渲染前,在这个函数之中我们可以异步向服务器端请求Render函数渲染需要使用的数据。Render函数是我们熟练掌握的渲染方法,在其中构建我们组件的UI。componentDidMount是在我们Render函数执行之后也就是已经渲染了我们DOM树之后触发,在这个函数中我们可以针对页面渲染完成之后希望进行处理的一系列动作。

组件更新(update)阶段

在讲述此阶段前需要先明确下react组件更新机制。setState引起的state更新或父组件重新render引起的props更新,更新后的state和props相对之前无论是否有变化,都将引起子组件的重新render。

造成组件更新有两类(三种)情况:

1.父组件重新render
父组件重新render引起子组件重新render的情况有两种

a. 直接使用,每当父组件重新render导致的重传props,子组件将直接跟着重新渲染,无论props是否有变化。可通过shouldComponentUpdate方法优化。

class Child extends Component {
   shouldComponentUpdate(nextProps){ // 应该使用这个方法,否则无论props是否有变化都将会导致组件跟着重新渲染
        if(nextProps.someThings === this.props.someThings){
          return false
        }
    }
    render() {
        return <div>{this.props.someThings}</div>
    }
}

b.在componentWillReceiveProps方法中,将props转换成自己的state

class Child extends Component {
    constructor(props) {
        super(props);
        this.state = {
            someThings: props.someThings
        };
    }
    componentWillReceiveProps(nextProps) { // 父组件重传props时就会调用这个方法
        this.setState({someThings: nextProps.someThings});
    }
    render() {
        return <div>{this.state.someThings}</div>
    }
}

根据官网的描述

在该函数(componentWillReceiveProps)中调用 this.setState() 将不会引起第二次渲染。

是因为componentWillReceiveProps中判断props是否变化了,若变化了,this.setState将引起state变化,从而引起render,此时就没必要再做第二次因重传props引起的render了,不然重复做一样的渲染了。

2.组件本身调用setState,无论state有没有变化。可通过shouldComponentUpdate方法优化。

class Child extends Component {
   constructor(props) {
        super(props);
        this.state = {
          someThings:1
        }
   }
   shouldComponentUpdate(nextStates){ // 应该使用这个方法,否则无论state是否有变化都将会导致组件重新渲染
        if(nextStates.someThings === this.state.someThings){
          return false
        }
    }

   handleClick = () => { // 虽然调用了setState ,但state并无变化
        const preSomeThings = this.state.someThings
         this.setState({
            someThings: preSomeThings
         })
   }

    render() {
        return <div onClick = {this.handleClick}>{this.state.someThings}</div>
    }
}

此阶段分为componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate

componentWillReceiveProps(nextProps)
此方法只调用于props引起的组件更新过程中,参数nextProps是父组件传给当前组件的新props。但父组件render方法的调用不能保证重传给当前组件的props是有变化的,所以在此方法中根据nextProps和this.props来查明重传的props是否改变,以及如果改变了要执行啥,比如根据新的props调用this.setState触发当前组件的重新render

shouldComponentUpdate(nextProps, nextState)
此方法通过比较nextProps,nextState及当前组件的this.props,this.state,返回true时当前组件将继续执行更新过程,返回false则当前组件更新停止,以此可用来减少组件的不必要渲染,优化组件性能

ps:这边也可以看出,就算componentWillReceiveProps()中执行了this.setState,更新了state,但在render前(如shouldComponentUpdate,componentWillUpdate),this.state依然指向更新前的state,不然nextState及当前组件的this.state的对比就一直是true了。

componentWillUpdate(nextProps, nextState)
此方法在调用render方法前执行,在这边可执行一些组件更新发生前的工作,一般较少用。

render
render方法在上文讲过。

componentDidUpdate(prevProps, prevState)
此方法在组件更新后被调用,可以操作组件更新的DOM,prevProps和prevState这两个参数指的是组件更新前的props和state

简言之,组件props或者state状态发生变化是所触发,通过对属性以及状态值进行监听可以得知他们发生了改变从而触发我们的render函数对相应的组件进行重新渲染。完成这一系列动作就达到了React组件自动更新的效果。

组件销毁阶段

此阶段只有一个生命周期方法:componentWillUnmount

componentWillUnmount
此方法在组件被卸载前调用,可以在这里执行一些清理工作,比如清楚组件中使用的定时器,清楚componentDidMount中手动创建的DOM元素等,以避免引起内存泄漏。

在这个生命周期中我们要确认对需要释放资源的部分进行释放。养成一个良好的编码习惯是很重要的。

React v16.4 的生命周期

变更缘由

原来(React v16.0前)的生命周期在React v16推出的Fiber之后就不合适了,因为如果要开启async rendering,在render函数之前的所有函数,都有可能被执行多次。

原来(React v16.0前)的生命周期有哪些是在render前执行的呢?

componentWillMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate

如果开发者开了async rendering,而且又在以上这些render前执行的生命周期方法做AJAX请求的话,那AJAX将被无谓地多次调用。。。明显不是我们期望的结果。而且在componentWillMount里发起AJAX,不管多快得到结果也赶不上首次render,而且componentWillMount在服务器端渲染也会被调用到(当然,也许这是预期的结果),这样的IO操作放在componentDidMount里更合适。

禁止不能用比劝导开发者不要这样用的效果更好,所以除了shouldComponentUpdate,其他在render函数之前的所有函数(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被getDerivedStateFromProps替代。

也就是用一个静态函数getDerivedStateFromProps来取代被deprecate的几个生命周期函数,就是强制开发者在render之前只做无副作用的操作,而且能做的操作局限在根据props和state决定新的state

React v16.0刚推出的时候,是增加了一个componentDidCatch生命周期函数,这只是一个增量式修改,完全不影响原有生命周期函数;但是,到了React v16.3,大改动来了,引入了两个新的生命周期函数。

新引入了两个新的生命周期函数:getDerivedStateFromProps,getSnapshotBeforeUpdate

getDerivedStateFromProps
getDerivedStateFromProps本来(React v16.3中)是只在创建和更新(由父组件引发部分),也就是不是不由父组件引发,那么getDerivedStateFromProps也不会被调用,如自身setState引发或者forceUpdate引发。

React v16.3
这样的话理解起来有点乱,在React v16.4中改正了这一点,让getDerivedStateFromProps无论是Mounting还是Updating,也无论是因为什么引起的Updating,全部都会被调用,具体可看React v16.4 的生命周期图。

React v16.4后的getDerivedStateFromProps

static getDerivedStateFromProps(props, state) 在组件创建时和更新时的render方法之前调用,它应该返回一个对象来更新状态,或者返回null来不更新任何内容。

getSnapshotBeforeUpdate
getSnapshotBeforeUpdate() 被调用于render之后,可以读取但无法使用DOM的时候。它使您的组件可以在可能更改之前从DOM捕获一些信息(例如滚动位置)。此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。

官网给的例子:

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    //我们是否要添加新的 items 到列表?
    // 捕捉滚动位置,以便我们可以稍后调整滚动.
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    //如果我们有snapshot值, 我们已经添加了 新的items.
    // 调整滚动以至于这些新的items 不会将旧items推出视图。
    // (这边的snapshot是 getSnapshotBeforeUpdate方法的返回值)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

总结

在本文中我们了解了React的生命周期,深入分析了React每个生命周期的意义。了解了利用生命周期中的函数能够帮助我们实现什么样的功能以及为什么要这么做。有了以上的只是基础我们对React的理解又更近一步。更够写出更加健壮完善的代码。

React v16.0前的生命周期与React v16.4 的生命周期不同点总结:

1、react16支持async rendering

2、react16.4 新引入了两个新的生命周期函数:getDerivedStateFromProps,getSnapshotBeforeUpdate

3、除了shouldComponentUpdate,其他在render函数之前的所有函数(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被getDerivedStateFromProps替代。

写在最后

✨原创不易,希望各位大佬多多支持。

👍点赞,你的认可是我创作的动力。

⭐️收藏,感谢你对本文的喜欢。

✏️评论,你的反馈是我进步的财富。

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

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

相关文章

XXE原理利用防御

XXE原理利用防御 一、XML定义 1、定义 XML用于标记电子文件使其具有结构性的标记语言&#xff0c;可以用来标记数据、定义数据类型&#xff0c;是一种允许用户对自己的标记语言进行定义的源语言。 2、原因 应用程序解析XML时&#xff0c;没有过滤外部实体的加载&#xff0…

多用户商城平台开发需要注意哪些问题?

电子商务的快速发展&#xff0c;越来越多的企业选择借助第三方商城软件开设自己的多用户商城平台&#xff0c;以此来帮助他们增加销售额和提高品牌知名度&#xff0c;如目前市面上常见的shop、shopnc等第三方商城软件。但是&#xff0c;多用户商城平台的开发并不是一件容易的事…

QFIELD-GIS工具版如何编辑数据

一、 简介 在现场进行GIS数据对比、采集、编辑是移动GIS App的一项非常实用的功能。能够使用户更加及时准确的收集到第一手资料&#xff0c;并在现场第一时间进行编辑和完善。同时配合遥感、GPS或移动设备自带各类传感器&#xff0c;再辅助以其它矢量参考数据可以对已有成果…

如何利用社交媒体来做Etsy店铺推广?

利用社交媒体是 Etsy 店铺推广的重要一环。通过创作优秀的社交媒体内容、定期发布内容、与关注者互动和利用广告&#xff0c;你可以吸引更多的潜在客户&#xff0c;增加你的店铺销售量和品牌影响力。以下是详细说明如何利用社交媒体来做店铺推广&#xff1a; 选择适合的社交媒体…

FinClip 现已支持云开发

在开发一个小程序时&#xff0c;除了考虑界面功能逻辑外&#xff0c;还需要后端的数据支持&#xff0c;开发者需要提前考虑服务器、存储和数据库等相关需求的支持能力&#xff0c;此外还可能需要花费时间精力在部署应用、和依赖服务的建设上。 因此&#xff0c;腾讯小程序为了实…

NetMQ | 实现TCP的发布订阅模式

NetMQ | 实现TCP的发布订阅模式 文章目录 NetMQ | 实现TCP的发布订阅模式前言什么是发布订阅模式&#xff1f;实现步骤步骤1&#xff1a;创建Publisher和Subscriber步骤2&#xff1a;绑定和连接步骤3&#xff1a;添加订阅步骤4&#xff1a;发布消息步骤5&#xff1a;接收消息 示…

构建一体化数字营销平台,助力医药企业实现销售转化能级大幅跃迁 | 案例研究

今日分享的案例企业成立于1994年&#xff0c;主要从事心血管、消化领域的药品生产、加工、分装和销售&#xff0c;其中心血管相关药品广泛畅销至世界很多个国家。目前&#xff0c;该医药公司销售网络遍及全国80余个城市&#xff0c;以专业人员组成的营业队伍&#xff0c;致力于…

【Linux系统安装Python3 --- 思路清晰的五大步】

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 目录 一、检查Python版本 二、下载源码包 三、解压编译源码 四、安装Python 五、调整系统默认Python指向 一、检查Python版本 1.直接进入python命令行查看python版本 python 2.列出系统上所…

[Android 模块化配置实践] Java + Gradle7配置模块化实践记录

文章目录 1.项目配置及环境2.项目工程结构3.Project下的系列设置自定义config.gradlesetting.gradlebuild.gradle(:project) 添加modulemodule_common下的build.gradle配置遇到的报错一遇到的报错二 applicationId问题 module_xxx下的build.gradle示例 由于目前刚开始学习模块化…

【vxe-table】自定义表头列是否可以排序

vxe-table真是让人又爱又恨&#xff0c;官网示例还有文档都很详细&#xff0c;但是可能是用的人少&#xff0c;每次遇到问题&#xff0c;都百度不到啥解决方法&#xff0c;不像el-table,全是方法 今天给我提了个bug&#xff0c;vxe-table要支持指定列排序&#xff0c;意思就是…

如何用3D人脸扫描设备制作虚拟数字人?

在海心沙元宇宙音乐会上&#xff0c;虚拟数字人“杜杜”与真人主持杜雨轩老师同台主持&#xff0c;带领现场观众感受虚实融合的音乐世界。 其实虚拟数字人“杜杜”是使用了数字人复刻技术&#xff0c;以真人主持杜雨轩老师1&#xff1a;1复刻的。在模型制作上不同于往常的美型数…

springboot整合flowable工作流引擎的简单使用

内容来自网络整理&#xff0c;文章最下有引用地址&#xff0c;可跳转至相关资源页面。若有侵权请联系删除 环境&#xff1a; mysql5.7.2 springboot 2.3.9.RELEASE flowable 6.7.2 采坑&#xff1a; 1.当前flowable sql需要与引用的pom依赖一致&#xff0c;否则会报library…

【chapter29】【PyTorch】[Regularization】

前言&#xff1a; 前面讲了Overfitted,这里重点讲解一下如何防止 Overfitting ,以及其中的方案之一 Regularization 模型的参数量,模型的表达能力远超模型本身复杂度. 与之对应的是奥卡姆剃刀原理&#xff1a; 如何用最简单的方法得到最好的效果 找到关键的部分&#xff0c;简…

【SWAT水文模型】SWAT水文模型建立及应用第三期:土壤库建立(待更新)

SWAT水文模型建立及应用&#xff1a;土壤库建立 1 简介2 土壤数据下载2.1 数据下载方式2.1.1 世界土壤数据库HWSD数据2.1.2 中国土壤数据库 2.2 数据下载 3 土壤数据的准备3.1 SWAT土壤数据库参数3.2 土壤质地转化3.3 土壤参数的提取3.4 其他变量的提取3.5 土壤类型分布图的处理…

回顾 | Pre VS Code Day - 用 GitHub Codespaces 构建 OpenAI 应用实战

编辑&#xff1a;Alan Wang 排版&#xff1a;Rani Sun 微软 Reactor 为帮助广开发者&#xff0c;技术爱好者&#xff0c;更好的学习 .NET Core, C#, Python&#xff0c;数据科学&#xff0c;机器学习&#xff0c;AI&#xff0c;区块链, IoT 等技术&#xff0c;将每周三到周六&a…

85.qt qml-炫酷烟花粒子特效(支持多种爆炸模式、爆炸阴影、背景场景)

效果如下所示: 截图如下所示: 实现内容如下所示: 1.实现多个爆炸效果2.爆炸的时候增加光度阴影效果3.由于场景有湖面,所以还需要增加一个倒影粒子组首先我们来学习下,该示例中所需要常用的类型点 1.如何更改粒子生命周期时的颜色变换动画 方法有两种。 1.1通过colorTable和si…

详谈Android进程间的大数据通信机制:LocalSocket

前言 说起Android进行间通信&#xff0c;大家第一时间会想到AIDL&#xff0c;但是由于Binder机制的限制&#xff0c;AIDL无法传输超大数据。 比如我们在之前文章《WebRtc中是如何处理视频数据的&#xff1f;》提到的我们可以得到WebRtc的视频数据&#xff0c;这时候我们如果有…

C++类和对象(4)

C类和对象 1.拷贝构造函数1.1 概念1.2. 特征1.2.1. 拷贝构造函数构造函数的一种重载形式&#xff1b;1.2.2. 拷贝构造函数的参数只能有一个&#xff0c;是对本类类型对象的引用&#xff0c;不能是传值调用&#xff0c;编译会直接报错&#xff0c;或者是直接进入死循环。1.2.3. …

wvp开发环境搭建

代码下载地址 代码下载地址 https://gitee.com/pan648540858/wvp-GB28181-pro.git 开发工具 采用jetbrain idea 利用开发工具下载代码 文件-新建-来自版本控制的项目 url是上面的代码下载链接&#xff0c;点击克隆即可 下图是已经克隆并打开的代码 安装依赖环境 安装redi…

基于html+css的图展示44

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…