React16.3新的生命周期详解

2023-11-13

一、React v16.0前的生命周期

 

1.1 第一个是组件初始化(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);
  }
}

1.2 第二个是组件的挂载(Mounting)阶段

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

1.2.1 componentWillMount

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

1.2.2 render

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

1.2.3 componentDidMount

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

1.3 第三个是组件的更新(update)阶段

setState引起的state更新或父组件重新render引起的props更新,更新后的stateprops相对之前无论是否有变化,都将引起子组件的重新render

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

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>
    }
}

1.3.2 componentWillReceiveProps(nextProps)

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

1.3.3 shouldComponentUpdate(nextProps, nextState)

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

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

1.3.4 componentWillUpdate(nextProps, nextState)

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

1.3.5 componentDidUpdate(prevProps, prevState)

此方法在组件更新后被调用,可以操作组件更新的DOMprevPropsprevState这两个参数指的是组件更新前的propsstate

1.4 卸载阶段

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

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

二、React v16.4 的生命周期

React v16.4 的生命周期图

2.1 变更缘由

原来(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在服务器端渲染也会被调用到

  • 所以除了shouldComponentUpdate,其他在render函数之前的所有函数(componentWillMountcomponentWillReceivePropscomponentWillUpdate)都被getDerivedStateFromProps替代
  • 也就是用一个静态函数getDerivedStateFromProps来取代被deprecate的几个生命周期函数,就是强制开发者在render之前只做无副作用的操作,而且能做的操作局限在根据propsstate决定新的state

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

2.2 引入了两个新的生命周期函数

2.2.1 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来不更新任何内容

2.2.2 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>
    );
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React16.3新的生命周期详解 的相关文章

  • 总结12个python代码

    python有很好的可读性和简洁性 学会其中的小的技巧 运用的恰当 会让我们的工作事半功倍 以下是我总结的12个小的程序段 看似非常的简单 但是却非常的有技巧性 并且对个人的编程能力是一个很好的检验 大家应该在日常的编程中多多使用 多多练习
  • 【精华】安卓开发学习路线规划

    近一段时间经常被朋友问到如何从零开始学习安卓 成为一名安卓开发工程师 不得不感叹 现在各行各业都有不少人在涌向IT 互联网行业 希望从事程序开发工作 竞争越来越激烈了 借此机会 我梳理了一下自己所学所知的安卓知识 制定了这份安卓开发学习路线
  • c语言中swap表示什么意思,swap是什么意思_单片机里的SWAP A是什么意思啊?

    Swap是什么意思 Swap是一种金融衍生品 指交易双方约定在未来某一期限相互交换各自持有的资产或现金流的交易形式 外汇里的 swap 是什么意思 外汇里swap专业说法是掉期 通俗的说法就是隔夜利息 指的是你炒外汇使用的杠杆部分的资金你应
  • leetCode Q3:Longest Substring Without Repeating Characters(java)

    1 题目链接 https leetcode com problems longest substring without repeating characters description 2 题目内容 中文版 给一个字符串 要求返回最长的不

随机推荐

  • 详解用户画像

    01画像简介 用户画像 即用户信息标签化 通过收集用户的社会属性 消费习惯 偏好特征等各个维度的数据 进而对用户或者产品特征属性进行刻画 并对这些特征进行分析 统计 挖掘潜在价值信息 从而抽象出用户的信息全貌 如图1 1所示 用户画像可看作
  • 史上最全C/C++面试八股文,一文带你彻底搞懂C/C++面试!

    前述 本文初衷是为了总结本人在各大平台看到的面经 我会在本文持续更新我所遇到的一些C 面试问题 如有错误请一定指正我 目录 1 讲一讲封装 继承 多态是什么 2 多态的实现原理 实现方式 是什么 以及多态的优点 特点 3 final关键字的
  • PHP实现微信公众号主动推送消息

    这篇文章主要介绍了php实现微信公众号主动推送消息的方法 PHP版微信公共平台消息主动推送 突破订阅号一天只能发送一条信息限制 需要的朋友可以参考下 通过学习借鉴朋友的实现方法进行整理 实现了PHP版的微信公共平台消息主动推送 分享给大家供
  • Kafka的数据消费过程以及消息不丢失机制

    文章目录 Kafka数据写入流程 Kafka数据消费流程 消息不丢失机制 broker数据不丢失 生产者数据不丢失 消费者数据不丢失 Kafka数据写入流程 执行流程 生产者获取对应分区的 leader 位置 发数据给leader brok
  • 区别VAN与GAN,LSGAN、WGAN、WGAN-GP、CGAN

    训练 稳定 样本的 多样性 和 清晰度 似乎是GAN的 3大指标 David 9 VAE与GAN 聊到随机样本生成 不得不提VAE与GAN VAE用KL divergence和encoder decoder的方式逼近真实分布 但这些年GAN
  • String、StringBuffer、StringBuilder的区别——(面试题)

    String StringBuffer StringBuilder的区别 String StringBuffer StringBuilder 执行速度 最差 其次 最高 线程安全 线程安全 线程安全 线程不安全 使用场景 少量字符串操作 多
  • Go开发工具

    http studygolang com articles 1678 1 4 Go开发工具 本节我将介绍几个开发工具 它们都具有自动化提示 自动化fmt功能 因为它们都是跨平台的 所以安装步骤之类的都是通用的 LiteIDE LiteIDE
  • 【ML on Kubernetes】第 3 章:探索 Kubernetes

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • SCPI 语言简介

    电子负载中需要用到 所以记录下 来源是德科技 SCPI 可编程仪器的标准命令 是一种基于 ASCII 的仪器编程语言 供测试和测量仪器使用 SCPI 命令采用分层结构 也称为树系统 相关命令归组于共用结点或根 这样就形成了子系统 下面一部分
  • FIO的基本概念

    对于FIO 其是一个10测试工具 可以运行在多种操作系统上 用来测试本地磁盘 网络存储等的性能 FIO有以下基本概念 大家可以先了解一下 1 基本概念 I O类型 顺序读 顺序写 随机读 随机写 块大小 读写时规定的block size 一
  • Keras入门(二)模型的保存、读取及加载

    本文将会介绍如何利用Keras来实现模型的保存 读取以及加载 本文使用的模型为解决IRIS数据集的多分类问题而设计的深度神经网络 DNN 模型 模型的结构示意图如下 具体的模型参数可以参考文章 Keras入门 一 搭建深度神经网络 DNN
  • Mathematica定义函数

    Mathematica定义函数时有点特殊 需在变量后加一个下划线 具体见下面示例 上面示例中定义函数时用的是 其实也可以用 这两个有什么区别呢 具体见下面示例便知 总结 Mathematica定义函数时 变量后面应加一个下划线 然后尽量用
  • DCDC电源负载瞬态响应分析

    DCDC电源负载瞬态响应分析 负载瞬态响应 输出电压过冲现象及其产生原因 如何改善输出电压过冲 负载瞬态响应 当负载电流突然增大或减小时 在us或ns时间内发生较大变化 变化量设置为80 满载输出电流 输出电压的瞬态响应 输出电压过冲现象及
  • springboot处理 json 转换成 实体对象

    可以使用 RequestBody PostMapping add public Result add RequestBody LogisticsDemand demand if demand getRefreshTime null dema
  • Latex-遇到的各种公式和特殊字符

    用的是OverLeaf Sigmoid的写法 begin equation sigma x frac 1 1 e x end equation Softmax的写法 begin equation sigma t i frac e t i s
  • 在Linux(Ubuntu) 中安装mysql服务器并开启远程访问

    在以linux为内核的有centos和ubuntu 推荐大家使用ubuntu 因为使用的人数多 出现了问题方便及时解决问题 一 创建一个云主机 ssh root 39 107 227 105 The authenticity of host
  • 华为OD机试(JAVA)真题II

    华为题库已换 后续会令启专栏更新最新版 介意的勿订阅 介意的勿订阅 介意的勿订阅 华为机试有三道题目 第一道和第二道属于简单或中等题 分值为100分 第三道为中等或困难题 分值为200分 总分为400分 150分钟考试时间 之前通过为150
  • vs2019MSDN(离线帮助文档)的下载与使用

    像这样搬砖的事情最烦了 在这里给大家总结一下步骤 本文参考 https blog csdn net weixin 41234001 article details 103308659 MSDN是vs的一个离线帮助文档 相当于帮助手册 1 检
  • Java中Map.Entry详解

    关于HashMap的详细介绍请参考Java基础 HashMap集合 1 Map Entry简介 Map是java中的接口 Map Entry是Map的一个内部接口 Map提供了一些常用方法 如keySet entrySet 等方法 keyS
  • React16.3新的生命周期详解

    一 React v16 0前的生命周期 1 1 第一个是组件初始化 initialization 阶段 也就是以下代码中类的构造方法 constructor Test类继承了react Component这个基类 也就继承这个react的基