目录
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
中处理一些清理工作