- React16 版本前与16版本后的生命周期。
React(后)生命周期
生命周期图谱
简略生命周期图谱

详细生命周期图谱

原来(React v16.0前)的生命周期在React v16推出的Fiber之后就不合适了,因为如果要开启async rendering,在render函数之前的所有函数,都有可能被执行多次。
原来(React v16.0前)的生命周期在render前执行的有:
- componentWillMount(已废除,被 getDerivedStateFromProps 替代)
- componentWillReceiveProps(已废除,被 getDerivedStateFromProps 替代)
- shouldComponentUpdate
- componentWillUpdate(已废除,被 getDerivedStateFromProps 替代)
如果开发者开了async rendering,而且又在以上这些 render 前执行的生命周期方法做 AJAX 请求的话,那 AJAX 将被无谓地多次调用。。。明显不是我们期望的结果。而且在 componentWillMount 里发起 AJAX,不管多快得到结果也赶不上首次 render,而且 componentWillMount 在服务器端渲染也会被调用到(当然,也许这是预期的结果),这样的 IO操作 放在 componentDidMount 里更合适。
禁止不能用比劝导开发者不要这样用的效果更好,所以除了 shouldComponentUpdate,其他在render函数之前的所有函数(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被 getDerivedStateFromProps 替代。
也就是用一个静态函数 getDerivedStateFromProps 来取代被 废弃的几个生命周期函数,就是强制开发者在 render 之前只做无副作用的操作,而且能做的操作局限在根据 props 和 state 决定新的 state。
getDerivedStateFromProps
getDerivedStateFromProps 取代 componentWillMount、componentWillReceiveProps、componentWillUpdate。
getDerivedStateFromProps 无论是 Mounting 还是 Updating,也无论是因为什么引起的 Updating,全部都会被调用,它应该返回一个对象来更新状态,或者返回null来不更新任何内容。
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate() 在 render 之后执行,而执行之时DOM元素还没有被更新,给了一个机会去获取DOM信息,计算得到一个 snapshot,这个 snapshot 会作为 componentDidUpdate 的第三个参数传入,snapshot 可以是任何值。
1 | getSnapshotBeforeUpdate(prevProps, prevState) { |
Mount(挂载)
使用:
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
废弃:
componentWillMount()
Update(更新)
使用:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
废弃:
componentWillReceiveProps()
componentWillUpdate()
Unmount(移除)
使用:
componentWillUnmount()
错误处理
当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:
React16(前)生命周期
生命周期图谱

初始化阶段
也就是以下代码中类的构造方法( constructor() ),Test 类继承了 react Component 这个基类,也就继承这个 react 的基类,才能有 render(),生命周期等方法可以使用,这也说明为什么函数组件不能使用这些方法的原因。
super(props)用来调用基类的构造方法( constructor() ), 也将父组件的 props 注入给子组件,功子组件读取(组件中 props 只读不可变,state 可变)。
而 constructor() 用来做一些组件的初始化工作,如定义 this.state 的初始内容。
1 | import React, { Component } from 'react'; |
Mount(挂载)
componentWillMount => render => componentDidMount
componentWillMount(Mount 前)
在组件挂载到DOM前调用,且只会被调用一次,在这边调用 this.setState 不会引起组件重新渲染,也可以把写在这边的内容提前到 constructor() 中,所以项目中很少用。
render
根据组件的 props 和 state(无两者的重传递和重赋值,论值是否有变化,都可以引起组件重新 render) ,return 一个 React 元素(描述组件,即UI),不负责组件实际渲染工作,之后由 React 自身根据此元素去渲染出页面 DOM。render 是纯函数(Pure function:函数的返回结果只依赖于它的参数;函数执行过程里面没有副作用),不能在里面执行 this.setState,会有改变组件状态的副作用(指当调用函数时,除了返回函数值之外,还对主调用函数产生附加的影响。例如修改全局变量(函数外的变量)或修改参数)。
componentDidMount(Mount 后)
组件挂载到DOM后调用,且只会被调用一次
Update(更新)
componentWillReceiveProps => shouldComponentUpdate => componentWillUpdate => render => componentDidUpdate
在讲述此阶段前需要先明确下 react 组件更新机制。setState 引起的 state 更新或父组件重新 render 引起的 props 更新,更新后的 state 和 props 相对之前无论是否有变化,都将引起子组件的重新 render。
造成组件更新有两类(三种)情况
- 父组件重新render
子组件显示父组件穿过来的props有两种方式:
- 直接使用
这种方式,父组件改变props后,子组件重新渲染,由于直接使用的props,所以我们不需要做什么就可以正常显示最新的props:
1 | class Child extends Component { |
- 转换成自己的
state
这种方式,由于我们使用的是state,所以每当父组件每次重新传递props时,我们需要重新处理下,将props转换成自己的state,这里就用到了 componentWillReceiveProps。
每次子组件接收到新的 props,都会重新渲染一次,除非你做了处理来阻止(比如使用:shouldComponentUpdate),但是你可以在这次渲染前,根据新的 props 更新 state,更新 state 也会触发一次重新渲染,但 react 不会这么傻,所以只会渲染一次,即官网的:
在该函数(componentWillReceiveProps)中调用 this.setState() 将不会引起第二次渲染。
1 | class Child extends Component { |
- 组件本身调用
setState,无论state有没有变化。可通过shouldComponentUpdate方法优化。
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。
Unmount(卸载)
componentWillUnmount
此方法在组件被卸载前调用,可以在这里执行一些清理工作,比如清楚组件中使用的定时器,清楚 componentDidMount中手动创建的DOM元素等,以避免引起内存泄漏。