时隔一年半之久再次重新学习 React,好多都还是原来的样子,这次我要重新开启 React 的大门,希望各位小伙伴可以一起讨论学习呦~
前言
今天我们开启第二个专题:React 中生命周期钩子的使用。我们在学习每个框架的生命周期的时候,都不是去死记硬背他们的顺序和作用,而是应该去结合我们在实际应用开发过程中对这些生命周期的需求,来帮助我们完成一些事情。
在新环境下,我们默认都是基于 React 16.4 之后的生命周期进行开发学习,下面的内容也是基于 16.4 版本的生命周期钩子,如果觉得有问题,可以先看一下对应的版本。
React 生命周期图示
为了便于区分,下面展示了V16.3之前 和 V16.4 之后版本,小伙伴们只需要了解一下即可,我们主要还是对 V16.4 之后版本进行介绍。
V16.3 之前版本:
V16.4 之后版本:
图片来源:https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
生命周期执行顺序
React 的生命周期一般分为挂载、渲染、卸载三个阶段,但是在 React 的整个生命周期中也提供很多钩子函数在生命周期的不同时刻来调用。
1. 挂载过程
当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
注意:
componentWillMount()
生命周期即将过时,在新代码中应该避免使用。
2. 更新过程
当组件的 props
或 state
发生变化时会触发更新,组件更新的生命周期调用顺序如下:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
注意:在这个阶段的
componentWillUpdate()
、componentWillReceiveProps()
生命周期即将过时,在新代码中应该避免使用。
3. 卸载过程
当组件从 DOM 中移除时,组件更新的生命周期调用顺序如下:
componentWillUnmount()
4. 错误处理
当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:
static getDerivedStateFromError()
componentDidCatch()
生命周期函数
constructor()
在 React 组件挂载之前被调用,如果不初始化 state
或不进行方法绑定,则不需要为 React 组件实现构造函数。当实现 React.Component
的子类的构造函数时,要在第一行加上 super(props)
。
- 应用情况:
- 通过给
this.state
赋值对象来初始化内部state
。不需要在构造函数中调用
setState()
,只需将初始状态设置给this.state
即可 。 - 为 事件处理函数 绑定实例。
- 通过给
如果没有初始化状态(state),并且没有绑定方法,通常不需要为 React 组件实现一个构造函数。
import React, {
Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
}
}
static getDerivedStateFromProps()
getDerivedStateFromProps
在每次调用 render
方法之前调用。包括初始化和后续更新时。
- 参数:
static getDerivedStateFromProps(nextProps, prevState)
- 第一个参数为即将更新的
props
值,第二个参数为之前的state
值
- 第一个参数为即将更新的
- 返回值:返回为
null
时,不做任何副作用处理。如果想更新某些state
状态值,则返回一个对象,就会对state
进行修改。 - 注意:该生命周期是静态函数,属于类的方法,其作用域内是找不到
this
的。并且 每次都会在渲染前触发此方法。
static getDerivedStateFromProps(nextProps, prevState) {
// ...
}
render()
render()
是类组件中唯一必须的方法,其余生命周期不是必须要写。
组件渲染时会走到该生命周期,展示的组件都是由 render() 生命周期的返回值来决定。
如果
shouldComponentUpdate()
方法返回 false ,render()
不会被调用。
render() {
}
componentDidMount()
在组件装载(mounting)(插入树)后被立即调用。
- 用途:
- 发送网络请求、启用事件监听
- 可以在此生命周期中立刻调用
setState()
shouldComponentUpdate()
在组件准备更新之前调用,可以控制组件是否进行更新,返回 true 时组件更新,返回 false 组件不更新。
- 参数:
shouldComponentUpdate(nextProps, nextState)
- 第一个是即将更新的
props
值,第二个是即将跟新后的state
值,可以根据更新前后的props
或state
进行判断,决定是否更新,进行性能优化
- 第一个是即将更新的
- 返回值:返回为
null
时,不做任何副作用处理。如果想更新某些state
状态值,则返回一个对象,就会对state
进行修改。 - 注意:不要
shouldComponentUpdate
中调用setState()
,否则会导致无限循环调用更新、渲染,直至浏览器内存崩溃。
static shouldComponentUpdate(nextProps, nextState) {
// ...
}
getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate()
在最近一次的渲染输出被提交之前调用。也就是说,在 render
之后,即将对组件进行挂载时调用。
它可以使组件在 DOM 真正更新之前捕获一些信息(例如滚动位置),此生命周期返回的任何值都会作为参数传递给 componentDidUpdate()
。如不需要传递任何值,那么请返回 null
getSnapshotBeforeUpdate(prevProps, prevState) {
}
componentDidUpdate()
componentDidUpdate()
在更新发生之后立即被调用。这个生命周期在组件第一次渲染时不会触发。
可以在此生命周期中调用
setState()
,但是必须包含在条件语句中,否则会造成无限循环,最终导致浏览器内存崩溃。
componentDidUpdate(prevProps, prevState, snapshot) {
}
componentWillUnmount()
componentWillUnmount()
在组件即将被卸载或销毁时进行调用。
此生命周期是取消网络请求、移除监听事件、清理 DOM 元素、清理定时器等操作的好时机。
componentWillUnmount()
中不应调用setState()
,因为该组件将永远不会重新渲染,组件实例卸载后,将永远不会再挂载它。
componentWillUnmount() {
}
static getDerivedStateFromError()
此生命周期会在后代组件抛出错误后被调用,它将抛出的错误作为参数,并返回一个值以更新state
。
getDerivedStateFromError()
会在渲染阶段调用,因此不允许出现副作用,如遇此类情况,请改用componentDidCatch()
。
static getDerivedStateFromError(error) {
}
componentDidCatch()
此生命周期在后代组件抛出错误后被调用,componentDidCatch()
会在提交阶段被调用,因此允许执行副作用,它应该用于记录错误之类的情况。
- 参数:
componentDidCatch(error, info)
componentDidCatch(error, info) {
}
// 两个参数:
// error: 抛出的错误
// info: 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息。
希望以上内容可以帮助到大家。我也是重新开始学习 React,欢迎大家一起讨论学习,最后不要忘记一键三连哦~
各位 加油!
参考内容:
React 超详细入门知识?(https://github.com/beichensky/Blog/issues/3)