携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
React生命周期的简单对比
一、不同版本React生命周期图示
1. 旧版React生命周期 —— React < V16
2. 新版React生命周期 —— React >= V16
注意 V16.3 和 V16.4 之间有细微的区别,主要是在static getDerivedStateFromProps的触发时机上
二、React 16+ 版本之后有哪些变化?
1. 简而言之
移除(添加声明UNSAFE)
- UNSAFE_componentWillMount
- UNSAFE_componentWillReceiveProps
- UNSAFE_componentWillUpdate
新增
+ getDerivedStateFromProps
+ getSnapshotBeforeUpdate
2.为什么要作出这些变化?
React V16 引入了 Fiber 机制
Fiber 是 React V16 对 React 核心算法的一次重写,简单的理解就是 Fiber 会使原本同步的渲染过程变成增量渲染模式。Fiber带来了两个重要的新特性:任务分解 与 渲染过程可打断。Fiber 机制更详细的介绍之后可能会新起一篇文章,这里主要是说一下Fiber 机制对旧版生命周期的影响。
从上面的图示可以看出,React生命周期大致可以分为三个阶段
-
render 阶段:Pure and has no side effects. May be paused, aborted or restarted by React.
-
pre-commit 阶段:Can read the DOM.
-
commit 阶段:Can work with DOM, run side effects, schedule updates.
render 阶段 在执行过程中允许被打断和重启,
commit 阶段( 包括 pre-commit )则总是同步执行,一直更新界面直到完成。
在旧版生命周期中
Render 阶段
componentWillMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
Commit 阶段
componentDidMount
componentDidUpdate
componentWillUnmount
可以发现,在旧版生命周期中, componentWillMount, componentWillReceiveProps, componentWillUpdate,都是处于render 阶段,可能会被打断或者重启多次,从而导致一些不可预测的bug,所以应该避免去使用。
相应地,React V16 新增了两个新的生命周期函数来解决这个问题
getDerivedStateFromProps
:用于替换 componentWillReceivePropsgetSnapshotBeforeUpdate
:用于替换 componentWillUpdate
三、React V16 生命周期函数用法建议
class ExampleComponent extends React.Component {
// 用于初始化 state
constructor() {}
// 用于替换 `componentWillReceiveProps` ,该函数会在初始化和 `update` 时被调用
// 因为该函数是静态函数,所以取不到 `this`
// 如果需要对比 `prevProps` 需要单独在 `state` 中维护
static getDerivedStateFromProps(nextProps, prevState) {}
// 判断是否需要更新组件,多用于组件性能优化
shouldComponentUpdate(nextProps, nextState) {}
// 组件挂载后调用
// 可以在该函数中进行请求或者订阅
componentDidMount() {}
// 用于获得最新的 DOM 数据
getSnapshotBeforeUpdate() {}
// 组件即将销毁
// 可以在此处移除订阅,定时器等等
componentWillUnmount() {}
// 组件销毁后调用
componentDidUnMount() {}
// 组件更新后调用
componentDidUpdate() {}
// 渲染组件函数
render() {}
// 以下函数不建议使用
UNSAFE_componentWillMount() {}
UNSAFE_componentWillUpdate(nextProps, nextState) {}
UNSAFE_componentWillReceiveProps(nextProps) {}
}
四、 一些需要注意的问题
1. static getDerivedStateFromProps
getDerivedStateFromProps 是一个静态方法,静态方法存在于组件类上,不依赖于组件的实例而存在。所以应该避免在静态方法内部读取 this 对象。
2. getDerivedStateFromProps的返回值
需要从Props派生新的State:返回一个对象用来更新state
不需要更新state:返回 null
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.someMirroredValue !== nextProps.someValue) {
return {
derivedData: computeDerivedState(nextProps),
someMirroredValue: nextProps.someValue
}
}
// Return null to indicate no change to state.
return null
}