Description
V16.3 之前
我们可以将生命周期分为三个阶段:
- 挂载阶段
- 组件更新阶段
- 卸载阶段
分开来讲:
- 挂载阶段
constructor
:避免将 props 的值复制给 statecomponentWillMount
render
:react 最重要的步骤,创建虚拟 dom,进行 diff 算法,更新 dom 树都在此进行componentDidMount
- 组件更新阶段
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
- 卸载阶段
componentWillUnMount
这种生命周期会存在一个问题,那就是当更新复杂组件的最上层组件时,调用栈会很长,如果在进行复杂的操作时,就可能长时间阻塞主线程,带来不好的用户体验,Fiber 就是为了解决该问题而生。
V16.3 之后
Fiber 本质上是一个虚拟的堆栈帧,新的调度器会按照优先级自由调度这些帧,从而将之前的同步渲染改成了异步渲染,在不影响体验的情况下去分段计算更新。
对于异步渲染,分为两阶段:
reconciliation
:componentWillMount
componentWillReceiveProps
shouldConmponentUpdate
componentWillUpdate
commit
componentDidMount
componentDidUpdate
其中,reconciliation
阶段是可以被打断的,所以 reconcilation
阶段执行的函数就会出现多次调用的情况,显然,这是不合理的。
所以 V16.3 引入了新的 API 来解决这个问题:
-
static getDerivedStateFromProps
: 该函数在挂载阶段和组件更新阶段都会执行,即每次获取新的props
或state
之后都会被执行,在挂载阶段用来代替componentWillMount
;在组件更新阶段配合componentDidUpdate
,可以覆盖componentWillReceiveProps
的所有用法。同时它是一个静态函数,所以函数体内不能访问
this
,会根据nextProps
和prevState
计算出预期的状态改变,返回结果会被送给setState
,返回null
则说明不需要更新state
,并且这个返回是必须的。 -
getSnapshotBeforeUpdate
: 该函数会在render
之后, DOM 更新前被调用,用于读取最新的 DOM 数据。返回一个值,作为
componentDidUpdate
的第三个参数;配合componentDidUpdate
, 可以覆盖componentWillUpdate
的所有用法。
注意:V16.3 中只用在组件挂载或组件 props
更新过程才会调用,即如果是因为自身 setState 引发或者forceUpdate 引发,而不是由父组件引发的话,那么static getDerivedStateFromProps
也不会被调用,在 V16.4 中更正为都调用。
即更新后的生命周期为:
- 挂载阶段
constructor
static getDerivedStateFromProps
render
componentDidMount
- 更新阶段
static getDerivedStateFromProps
shouldComponentUpdate
render
getSnapshotBeforeUpdate
componentDidUpdate
- 卸载阶段
componentWillUnmount
更多请看 深入 React 生命周期