前端框架react----生命周期
目录
2、static getDerivedStateFromProps(props, state)
1、shouldComponentUpdate(nextProps, nextState)
2、getSnapshotBeforeUpdate(prevProps, prevState)
3、componentDidUpdate(prevProps, prevState, snapshot)
4、UNSAFE_componentWillUpdate(nextProps, nextState) 旧
5、UNSAFE_componentWillReceiveProps(nextProps) 旧
前言
前面两篇文章简单地介绍了 React 中的 JSX 语法、状态组件、绑定事件、设置 state 等基本操作,这篇文章将继续通过一些实例介绍 React 中的基础知识点生命周期。
文章开始之前我们来认识两张图:
旧版本:

新版本:

一、什么是组件的生命周期呢?
1、组件从创建到死亡它会经历一些特定的阶段。
2、React组件中包含一系列钩子函数(生命周期回调函数),会在特定的时刻调用。
3、我们在定义组件时,会在特定的生命周期回调函数中,做待定的工作。
简单来说:一个组件从创建到最后消亡所经历的各种状态,就是一个组件的生命周期
从组件被创建,到组件挂载到页面上运行,再到页面关闭组件被卸载,这三个阶段总是伴随着组件各种各样的事件,那么这些事件,统称为组件的生命周期函数
在React中,我们可以将其生命周期分为三个阶段:
-
挂载阶段
-
更新阶段
-
卸载阶段
不同阶段将对应不同的钩子函数来处理组件的状态。
二、挂在阶段
首先是挂载阶段,当组件实例被创建并插入DOM中时,将依次调用以下生命周期函数
-
constructor -
static getSerivedStateFromProps -
render -
componentDidMount
1、constructor(props)
在React组件挂载之前,会调用它的构造函数,在这个函数中我们可以拿到组件传递的props,通常,在React中,构造函数仅用于以下两种情况:
通过给this.state赋值对象来初始化内部state
为事件处理函数绑定实例
注意:
-
在
constructor()函数中不要调用setState()方法 -
避免将
props的值复制给state
---在 constructor() 函数中不要调用 setState() 方法。如果你的组件需要使用内部 state,请直接在构造函数中为 this.state 赋值初始 state:
constructor(props) {
super(props);
// 不要在这里调用 this.setState()
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
只能在构造函数中直接为 this.state 赋值。如需在其他方法中赋值,你应使用 this.setState() 替代。
---避免将 props 的值复制给 state!这是一个常见的错误:
constructor(props) {
super(props);
// 不要这样做
this.state = { color: props.color };
}
如此做毫无必要(你可以直接使用 this.props.color),同时还产生了 bug(更新 prop 中的 color 时,并不会影响 state)。
只有在你刻意忽略 prop 更新的情况下使用,此时,应将 prop 重命名为 initialColor 或 defaultColor。必要时,你可以修改它的key,以强制“重置”其内部 state。
2、static getDerivedStateFromProps(props, state)
getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容
在这个函数中,我们可以拿到组件传递的 props 和 state,它存在最重要的目的就是:让组件在 props 变化时更新 state
比如说,这样:
static getDerivedStateFromProps(props, state) {
console.warn('组件生命周期:getDerivedStateFromProps')
if (props.age !== state.age) {
return {
age: props.age
}
}
return null
}
使用该生命周期函数需要注意的地方:
-
该函数会在
render方法之前调用,会调用多次 -
必须有返回值,返回一个对象来更新
state或者返回null不更新state
3、render()
render()方法是class组件中唯一必须实现的方法
使用该函数需要注意的地方:
-
必须有返回值,可以有多种类型,如果不需要返回任何结构,可以直接返回
null -
render()函数应该为纯函数,意味着在不修改组件state的情况下,每次调用都会返回相同的结果,并且它不会直接与浏览器交互。 -
不能在函数中调用this.setState()方法
-
该函数会调用多次
-
如需与浏览器进行交互,请在
componentDidMount()或其他生命周期方法中执行你的操作。保持render()为纯函数,可以使组件更容易思考。
如果
shouldComponentUpdate()返回 false,则不会调用render()。
4、componentDidMount()
componentDidMount()会在组件挂载后(插入DOM树中)立即调用。依赖于DOM节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方
在该函数中常有的操作:
-
操作
DOM -
进行
ajax操作来完成数据的交互 -
使用
setState()来修改state
5、componentWillMount()
这个周期函数在上面第一张生命周期图中出现,在最新版本的生命周期中已经除去,在react17之前也叫UNSAFE_componentWillMount()。
它的特点:
-
UNSAFE_componentWillMount()在挂载之前被调用。 -
它在
render()之前调用,在此方法中同步调用setState()不会触发额外渲染 -
与现有的新生命周期不能同时使用,只会调用一次
三、更新阶段
当组件的
props或state发生变化时会触发更新
更新阶段会依次触发以下生命周期函数:
-
static getDerivedStateFromProps() -
shouldComponentUpdate() -
render() -
getSnapshotBeforeUpdate() -
componentDidUpdate()
在生命周期函数执行阶段,有一些钩子函数是多次触发,比如更新阶段的 static getDerivedStateFromProps() 与 render() 函数也会在挂载阶段触发。
1、shouldComponentUpdate(nextProps, nextState)
当props或state发生变化时,shouldComponentUpdate()会在渲染执行之前被调用,根据shouldComponentUpdate()的返回值,判断React组件的输出是否受当前state或props更改的影响。默认行为是state每次发生变化都会重新渲染。
使用该函数需要注意的地方:
-
在组件首次渲染的时候是不会调用这个生命周期函数的
-
在该函数中我们可以通过
this.state和this.props拿到更新之前的state与props的值;通过nextProps与nextState拿到props与state更新之后的值 -
该函数必须提供一个返回值,
true或者false。 默认返回true -
最好不要企图依靠此方法来阻止渲染 ( 返回
false)
2、getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate()在最近一次渲染输出(提交到DOM节点)之前调用
简单来说,这个函数会在 componentDidUpdate() 函数执行之前调用,一般会用于一些UI的处理 需要注意的点:
-
在这个函数中我们可以拿到组件更新之前的
props与state的值 -
必须与
componentDidUpdate()一起使用 -
必须提供返回值
snapshot的值( 在componentDidUpdate()中接收 )或null
3、componentDidUpdate(prevProps, prevState, snapshot)
componentDidUpdate()会在更新后会被立即调用。首次渲染不会执行此方法
使用该函数需要注意的点:
-
当组件更新后,可以在此处对
DOM进行操作 -
可以选择在此处进行网络请求
-
可以直接调用
setState(),但是必须将它包裹在一个条件语句中 -
如果
shouldComponentUpdate()返回值为false,则不会调用componentDidUpdate() -
在该函数中可以拿到 更新之前的
state与props值,也可以拿到getSnapshotBeforeUpdate()传递过来的值,如果并没有传递值,则第三个参数的值为undefined
4、UNSAFE_componentWillUpdate(nextProps, nextState) 旧
此生命周期之前名为
componentWillUpdate。该名称将继续使用至React 17
使用该函数需要注意的地方:
-
当组件收到新的
props或state时,会在渲染之前调用UNSAFE_componentWillUpdate() -
不能此方法中调用
this.setState() -
如果
shouldComponentUpdate()返回false,则不会调用UNSAFE_componentWillUpdate() -
不要与新的生命周期一起使用(会出现警告)
5、UNSAFE_componentWillReceiveProps(nextProps) 旧
此生命周期之前名为
componentWillReceiveProps。该名称将继续使用至React 17
UNSAFE_componentWillReceiveProps()会在已挂载的组件接收新的props之前被调用
使用该函数需要注意的地方:
-
React不会针对初始props调用UNSAFE_componentWillReceiveProps(),只会在组件的props更新时调用此方法 -
调用
this.setState()通常不会触发UNSAFE_componentWillReceiveProps() -
不要与新的生命周期函数一起使用
四、卸载阶段
React 在卸载阶段只有一个生命周期函数
1、componentWillUnmount()
componentWillUnmount() 会在组件卸载及销毁之前直接调用
使用该函数的注意点:
-
可以在该函数中执行必要的清理工作,比如 定时器
-
componentWillUnmount()中不应调用setState(),因为该组件将永远不会重新渲染
下面就是一个基本完整的 React 组件从挂载到 子组件卸载的完整过程

总结
一个组件从开始挂载到最终卸载生命周期(主要)
| 生命周期 | 调用次数 | 是否可以使用 setState |
|---|---|---|
constructor() | 1 | 否 |
render() | >= 1 | 否 |
componentDidMount() | 1 | 是 |
componentDidUpdate() | >=1 | 是(必须被包裹在一个条件语件里) |
componentWillUnmount() | 1 | 否 |
-
React中必须实现的生命周期只有render -
在
constructor中进行state的初始化与事件绑定 -
在
componentDidMount与componentDidUpdate中进行一些DOM操作和数据交互,使用setState -
在
componentWillUnmount中处理一些清理工作