新旧版本生命周期图对比

16.3之前的版本

16.3之后的版本

react自16.x之后,添加了getDerivedStateFromProps, getSnapshotBeforeUpdate,如图

生命周期的几个阶段

生命周期有几个时期,分别为挂载,更新,卸载,我们看上方16.3之后版本的图可以得出,其实每个时期还分为几个阶段:

  • render阶段: 是指从到render函数执行完返回jsx结构之前的过程,这个过程的都是不包含副作用的纯函数,这个过程包含的函数有

    • constructor
    • getDerivedStateFromProps
    • shouldUpdateComponent
    • render
    • getDerivedStateFromError
  • pre-commit阶段: 是指从返回一个jsx结构到更新dom之前的过程,这个过程只有函数getSnapshotBeforeUpdate
  • commit阶段: 是指更新dom,以及更新成功之后的过程,有函数
    • componentDidMount
    • componentDidUpdate
    • componentDidCatch

从上图中看函数componentWillUnmount是在commit阶段但是,我理解这个函数应该是在dom更新之前执行,我认为应该在pre-commit

挂载

所谓挂载其实就是组件第一次在dom树种渲染的过程,在这个过程中会一次执行一些生命周期函数

constructor

构造函数用于初始化props,state以及绑定this指向,如果不需要这些操作可以省略构造函数,需要注意的是

  • 构造函数中不能调用setState, 而应该直接给state赋值
  • props是由外部传进来的,所以不能修改props
  • 不能直将props中的值赋值给state,像这样
constructor(props) {
super(props);
// 不要这样做
this.state = { color: props.color };
}

参考react官网介绍

conpomentWillMount(v17将移除)

这个方法会在render之前执行,这个方法也是在服务端渲染中唯一会调用的方法

getDerivedStateFromProps(v16.3加入)

conpomentWillMount 移除了取而代之的就是这个方法,这是一个静态方法,实例无权访问,在组件实例化之后,以及每次render之前调用。getDerivedStateFromProps的存在只有一个目的就是让props更新的时候更新state,在这一点上跟componentWillReceiveProps是一致的,这两个生命周期函数并不是只有在props更新的时候才会调用,而是当父组件重新渲染后,两个生命周期函数都会调用

static getDerivedStateFromProps(props, state)

render

组件的render函数并不会像dom中插入元素,实际上render只是返回jsx结构,或者是数组,字符串等数据,最终由ReactDOM.render渲染到dom中,在自定义的类组件中,render函数必须实现,并且render应该为一个根据state和props来返回结果,不造成副作用的纯函数

componentDidMount

在组件被挂载(插入到dom节点)后,立刻执行这个函数,可以在这个函数中请求数据,以及添加订阅,但是要记得在函数componentWillUnmount中去取消订阅

更新

当组件的props更新时,或者state更新时也会触发一些生命周期函数来更新dom

props更新 componentWillReceiveProps(v17将移除)

当父组件的render被调用时,无论传进来的props是否更新,这个函数都会调用,需要注意的是,在函数调用时,应该将参数与props做一个对比,判断是否要更新state

  componentWillReceiveProps(nextProps) {
// 只要 props.email 改变,就改变 state
if (nextProps.email !== this.props.email) {
this.setState({
email: nextProps.email
});
}
}

这个方法state更新时不会执行,v17之后由getDerivedStateFromProps取代

shouldComponentUpdate

这个函数返回一个布尔值,返回true的时候接下来会执行组件的render方法,默认情况下都是返回true的,如果为false则不会执行后续渲染,这个方法在挂载阶段或者执行forceUpdate时不会执行。

shouldComponentUpdate(nextProps, nextState)

函数接受的参数为新的props和新的state所以在函数内部可以拿新的props和state与组件当前的props、state做一个对比,如果发现没有变化则返回false。React官方建议使用React.PureComponent实现组件,这个组件的shouldComponentUpdate方法会对props和state分别做浅层对比,以此来提高性能,同时不建议在shouldComponentUpdate中去实现深层次的数据对比,以免影响效率

componentWillUpdate(v17将移除)

shouldComponentUpdate返回true,则会执行componentWillUpdate,在这个方法中,不能执行setState等其它会更新组件的方法(比如dispatch),可以在此方法中读取 DOM 信息(例如,为了保存滚动位置),而在之后可以放到getSnapshotBeforeUpdate

getSnapshotBeforeUpdate(v16.3引入)

getSnapshotBeforeUpdate(prevProps, prevState)

在render之后,dom更新之前回执行这个函数,一般会在此时读取dom更新之前的一些信息(比如滚动条位置),此函数的所有返回值,都将作为参数传给componentDidUpdate

componentDidUpdate

componentDidUpdate(prevProps, prevState, snapshot)

这里第三个参数就为上文中getSnapshotBeforeUpdate的返回值,componentDidUpdate会在dom加载完之后执行,在这个函数中就可以进行dom操作了

卸载

componentWillUnmount

组件销毁之前调用,在这里更新state不会更新组件

错误处理

react在v16引入了错误边界的概念,当子组件发生,当子组件的构造函数,生命周期以及子组件的构造函数出出错的时候,会执行错误处理回调

getDerivedStateFromError

static getDerivedStateFromError(error)

当子组件抛出错误会触发这个函数,错误信息为函数的参数,次函数可以返回一个新的值来更新state,组件可以根据更新的state实现一个降级UI,此方法在“render阶段”执行,应该为一个纯函数

componentDidCatch

componentDidCatch(error, info)

同样当子组件抛出错误的时候回触发,第二个参数为info,其中包含了组件调用栈的信息

console.log(info.componentStack);

这个函数是在“commit阶段”执行的,所以可以在函数中调用setState来更新state

为什么react要在v17移除部分构造函数?

官方团队认为,之前的几个will生命周期函数会让用户产生很多误解,在实际的使用场景中,也有很多错误的使用情况出现。所以直接替换为一个静态方法getDerivedStateFromProps,这样用户就不能再这些方法内访问到当前的实例了,从而也就不能调用setState,或者访问refs了,减少了很多错误操作

其他原因可以参考链接

细说React生命周期的更多相关文章

  1. React生命周期

    在react生命周期中,分2段执行,一个挂载的生命周期,一个是组件发生了数据变动,或者事件触发而引发的更新生命周期. 注:react生命周期很重要,对于很多组件场景的应用发挥重要作用,而且不熟悉生命周 ...

  2. React 生命周期

    前言 学习React,生命周期很重要,我们了解完生命周期的各个组件,对写高性能组件会有很大的帮助. Ract生命周期 React 生命周期分为三种状态 1. 初始化 2.更新 3.销毁 初始化 1.g ...

  3. React生命周期详解

    React生命周期图解: 一.旧版图解: 二.新版图解: 从图中,我们可以清楚知道React的生命周期分为三个部分:  实例化.存在期和销毁时. 旧版生命周期如果要开启async rendering, ...

  4. React生命周期简单详细理解

    前言 学习React,生命周期很重要,我们了解完生命周期的各个组件,对写高性能组件会有很大的帮助. Ract生命周期 React 生命周期分为三种状态 1. 初始化 2.更新 3.销毁 初始化 1.g ...

  5. 22.1 、react生命周期(一)

    在每个react组件中都有以下几个生命周期方法~我们需要在不同阶段进行讨论 组件生命周期概述 1.初始化 在组件初始化阶段会执行 constructor static getDerivedStateF ...

  6. react 生命周期钩子里不要写逻辑,否则不生效

    react 生命周期钩子里不要写逻辑,否则不生效,要把逻辑写在函数里,然后在钩子里调用函数,否则会出现问题.

  7. react复习总结(2)--react生命周期和组件通信

    这是react项目复习总结第二讲, 第一讲:https://www.cnblogs.com/wuhairui/p/10367620.html 首先我们来学习下react的生命周期(钩子)函数. 什么是 ...

  8. React生命周期执行顺序详解

    文章内容转载于https://www.cnblogs.com/faith3/p/9216165.html 一.组件生命周期的执行次数是什么样子的??? 只执行一次: constructor.compo ...

  9. vue生命周期和react生命周期对比

    一 vue的生命周期如下图所示(很清晰)初始化.编译.更新.销毁 二 vue生命周期的栗子 注意触发vue的created事件以后,this便指向vue实例,这点很重要 <!DOCTYPE ht ...

随机推荐

  1. pytest封神之路第零步 快速入门

    背景:本文是在系列第五篇发表后的补充篇章,第一篇介绍了tep,可能对不熟悉pytest的朋友不够友好,特意补充入门篇,帮大家快速了解如何动手写pytest.如果你是从这篇文章第一次阅读,那么请忽略以上 ...

  2. Redis小记(三)

    1.复制 通过slaveof命令或设置slaveof选项,实现一个服务器去复制另一个服务器,被复制的是主服务器,执行复制的是从服务器,复制过程中主从双方数据库保持数据一致 2.8版本以前,可分为初次复 ...

  3. Python-鸡兔同笼问题

    鸡兔同笼问题 -- 今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何? --鸡和兔在一个笼子里,从上面数,有35个头:从下面数,有94只脚.问笼中各有几只鸡和兔 如何逻辑整理? -- 鸡头和兔子 ...

  4. MacOS下Terminal获取GPS经纬度坐标

    通过命令行直接获取经纬度坐标MacOS 首先下载WhereAmI,最新版本: https://github.com/robmathers/WhereAmI/releases/download/v1.1 ...

  5. Tensorflow学习笔记No.1

    使用tf.keras.Sequential()建立网络模型 整个过程可分为五步:1创建Sequential模型,2添加所需要的神经层,3使用.compile方法确定模型训练结构,4使用.fit方法 使 ...

  6. 一、Mysql(1)

    数据库简介 人类在进化的过程中,创造了数字.文字.符号等来进行数据的记录,但是承受着认知能力和创造能力的提升,数据量越来越大,对于数据的记录和准确查找,成为了一个重大难题 计算机诞生后,数据开始在计算 ...

  7. Python+Appium自动化测试(11)-location与size获取元素坐标

    appium做app自动化测试过程中,有时需要获取控件元素的坐标进行滑动操作.appium中提供了location方法获取控件元素左上角的坐标,再通过size方法获取控件元素的宽高,就可以得到控件元素 ...

  8. 天啦噜!知道硬盘很慢,但没想到比 CPU L1 Cache 慢 10000000 倍

    前言 大家如果想自己组装电脑的话,肯定需要购买一个 CPU,但是存储器方面的设备,分类比较多,那我们肯定不能只买一种存储器,比如你除了要买内存,还要买硬盘,而针对硬盘我们还可以选择是固态硬盘还是机械硬 ...

  9. MySQL - 常用三种数据库存储引擎

    数据库存储引擎:是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据.不同的存储引擎提供不同的存储机制.索引技巧.锁定水平等功能,使用不同的存储引擎,还可以获得特 ...

  10. 多测师讲解html _表格标签007_高级讲师肖sir

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>表 ...