react 生命周期分为 挂载时、更新时、卸载时 。
render 是唯一必须实现的组件生命周期。
先贴两张声明周期函数的图:
- 常用的生命周期函数
- 全部的生命周期函数
上面两张图的引用地址:
1 挂载
当组件被创建并插入 DOM 中时,生命周期执行顺序如下,常用的生命周期用黑体表示:
constructor()
static getDerivedStateFromProps(props, state)
render()
componentDidMount()
下面是即将过时的生命周期,新代码应避免使用:
- UNSAFE_componentWillMount
1.1 constructor
1.1.1 作用
初始化父类(使用
super(props)
语句)初始化 this.state
为事件处理函数绑定 this
1
2
3
4
5
6constructor(props) {
super(props);// 必须先执行此句
// 不要在这里调用 this.setState()
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
1.1.2 注意
- super(props) 必须在其他语句之前
- 在构造函数中只能直接为 this.state 赋值,其他地方只能通过调用 this.setState 来修改 state
1.2 getDerivedStateFromProps
1 | static getDerivedStateFromProps(props, state) |
创建组件以及每次组件由于 props 或 state 的改变而重新渲染时,此方法都会被调用。
只要父组件重新被渲染,此函数就会被调用,无论 props 和 states 是否发生变化。
返回值为对象用来更新 state,返回 null 表示不更新 state。
1.2.1 作用
监听 props 变化。
1.3 render
render 函数应该为纯函数,使用相同的 state 时,render 的调用结果应该是相同的。
1.3.1 作用
返回需要在界面展示的 UI 元素。
render 返回值为下面类型之一:
- react 元素
- 自定义组件或 原生的html 元素
- 数组 或 fragments
- 用于返回多个元素
- Protals
- 可以渲染子节点到不同的 DOM 子树中
- 字符串或数字
- 会被渲染成文本节点
- 布尔类型或 null
- 什么都不渲染(用于支持返回
bool && <Child />
的模式)
- 什么都不渲染(用于支持返回
1.3.2 注意
当 shouldComponentUpdate 返回 false 时,render 则不会被调用。
1.4 componentDidMount
组件插入 DOM 节点后会执行此函数。
1.4.1 作用
放置依赖于 DOM 节点的初始化的地方,如网络请求、添加事件监听等。
2 更新
当组件的 props 或 state 发生变化时,生命周期执行顺序如下,常用的用生命周期用黑体表示:
static getDerivedStateFromProps(props, state)
shoudComponentUpdate(nextProps, nextState)
render()
getSnapshotBeforeUpdate()
**componentDidUpdate(**prevProps, prevState, snapshot)
下面是即将过时的(17.x 版本时会废弃掉),新代码应避免使用:
UNSAFE_componentWillUpdate()
UNSAFE_componentWillReceiveProps()
2.1 getDerivedStateFromProps
2.2 shoudComponentDidUpdate
1 | shouldComponentUpdate(nextProps, nextState) |
react 会根据此函数的返回值来判断是否需要重新渲染组件,默认返回值为 true,表示需要重新渲染组件。
2.2.1 作用
此方法可以用来优化性能。
可以使用 PureComponent
组件来替代手动实现此函数,PureComponent
会对 props 和 state 进行浅层比较,并减少没必要的渲染。
2.2.2 注意
- 返回 false 不会阻止子组件在 state 更改时的渲染。
- 后续的 react 版本,当返回 false 时,组件可能已经会被重新渲染
- 不建议在此函数中进行深层比较,会影响性能
2.3 render
2.4 getSnapshotBeforeUpdate
1 | getSnapshotBeforeUpdate(prevProps, prevState) |
此方法的返回值 snapshot(或 null) 会作为 componentDidUpdate 的最后一个参数。
2.4.1 作用
使得能够在组件发生变化前,获取 dom 的一些信息(如滚动条位置)
2.5 componentDidUpdate
组件被更新后此函数会被立即调用。
2.1.1 作用
当组件更新后,可以在此处对 DOM 进行操作。
2.1.2 注意
在 componentDidUpdate 中调用 setState 时,必须被包裹在条件语句中个,否则可能会导致死循环
1
2
3
4
5
6componentDidUpdate(prevProps) {
// 典型用法(不要忘记比较 props):
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate()
3 卸载
3.1 componentWillUnmount
此函数在组件卸载销毁之前调用。
3.1.1 作用
在此方法中执行清理操作,如清除 timer、取消请求、取消监听等。
4 错误处理
当渲染过程、生命周期或子组件的构造函数中抛出错误时,会调用如下方法:
4.1 static getDerivedStateFromError()
此生命周期会在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state
1 | class ErrorBoundary extends React.Component { |
4.2 componentDidCatch()
此生命周期在后代组件抛出错误后被调用。 它接收两个参数:
error
—— 抛出的错误。info
—— 带有componentStack
key 的对象,其中包含有关组件引发错误的栈信息。
1 | class ErrorBoundary extends React.Component { |