react教程,如何理解类组件生命周期基本逻辑之更新?
发布于 作者:苏南大叔 来源:程序如此灵动~本文继续说react@18
的类式组件的生命周期,这是个比较长的话题,所以分为几部分来说。本文描述组件更新逻辑,组件更新这块,比较容易产生死循环或者无效更新。所以,更加需要清晰的生命周期。本文依然强调说的是react@18
的类式组件,无关函数式组件。
大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述类式组件的“组件更新”所涉及的生命周期。测试环境:create-react-app@5.0.1
,react@18.2.0
,react-dom@18.2.0
,node@16.14.2
。
前文回顾
理解本文,需要首先知道react@18
的组件挂载逻辑:
还需要知道,如何修改StrictMode
严格模式:
测试代码
本文测试代码如下:
import React, { Component } from 'react'
export default class index extends Component {
constructor(props) {
console.log("constructor");
super(props);
this.state = { msg: "苏南大叔" };
}
UNSAFE_componentWillReceiveProps(nextProps, nextContext) { // 过期
console.log("componentWillReceiveProps");
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate');
return true;
}
UNSAFE_componentWillUpdate() { // 过期
console.log('componentWillUpdate');
}
componentDidUpdate() {
console.log('componentDidUpdate');
}
test() {
this.setState({ 'msg': 'sunan' + Date.now() });
}
render() {
console.log("render");
return (
<div>
<button onClick={this.test.bind(this)}>{this.state.msg}</button>
</div>
)
}
}
外部组件通过修改props
来触发子组件的componentWillReceiveProps
生命周期。如下图所示:
UNSAFE_componentWillReceiveProps
从UNSAFE_
这个前缀可以看出,这个componentWillReceiveProps
必然是个被放弃的生命周期。如果想要以最正确的姿势使用它,可以考虑在非严格模式下,外加这个UNSAFE_
前缀使用。
测试代码:
UNSAFE_componentWillReceiveProps(nextProps, nextContext) { // 过期
console.log("componentWillReceiveProps");
console.log(`${JSON.stringify(this.props)}`);
console.log(`${JSON.stringify(nextProps)}`);
console.log(`${JSON.stringify(nextContext)}`);
if (nextProps.email !== this.props.email) {
this.setState({ email: nextProps.email });
}
}
看名字就可以看到,这个是由外部传递的props
引起的变动,和自身的state
值没有关系。外部props
变动,该生命周期根据props
的变化情况,来更新state
的数据。
shouldComponentUpdate
这个周期是比较重要的,可以用于性能优化。这个生命周期存在一个默认的返回值true
,表示可以更新组件。如果return false
,则不会触发组件更新。可以说是:一夫当关万夫莫开。
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate');
console.log(nextProps, nextState);
// return false;
return true;
}
shouldComponentUpdate
这个是类式组件的一个生命周期,实际上类式组件也存在着两种,分别是PureComponent
和React.Component
。而shouldComponentUpdate
和PureComponent
是存在冲突的,因为PureComponent
本身的定义是可以根据props
和state
自动判断是否需要更新组件的。所以,PureComponent
的生命周期里面,确实是不需要shouldComponentUpdate
的。
报错内容类似如下:
react-dom.development.js:86 Warning: Counter has a method called shouldComponentUpdate(). shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.
UNSAFE_componentWillUpdate
这个UNSAFE_
前缀,依然表明是个被放弃的生命周期,所以尽量不要使用这个生命周期。在react@18
环境下,只有在非严格模式,外加UNSAFE_
前缀的情况下,才不会触发warning
警告信息。
render
常规操作render
,需要注意的是:不要在render
(以及componentDidMount
)阶段实时修改state
,因为会触发死循环。
render() {
console.log("render");
return (
<div>
<button onClick={this.test.bind(this)}>{this.state.msg}</button>
</div>
)
}
componentDidUpdate
这个componentDidUpdate
阶段和componentDidMount
阶段不一样,不要试图在componentDidUpdate
阶段实时更新state
,会陷入死循环。
常规操作“更新完成”,注意在mount
阶段,除了render
外,本文缩写的各个生命周期都不会被触发。
本文相关的更新阶段生命周期触发的条件是:
- 外部修改了组件的
props
。 - 组件自身修改了
state
。
组件挂载和卸载,并不会触发“组件更新”相关生命周期。“组件更新”过程中,也不会触发"constructor",但是会触发"render"。
执行顺序
父组件修改props
,生命周期执行顺序为:componentWillReceiveProps
=> shouldComponentUpdate
=> componentWillUpdate
=> render
=> componentDidUpdate
自身修改state
,生命周期执行顺序为:shouldComponentUpdate
=> componentWillUpdate
=> render
=> componentDidUpdate
两者就差最开始的一步:componentWillReceiveProps
。
被替换的生命周期
在本文中,UNSAFE_componentWillReceiveProps
和UNSAFE_componentWillUpdate
是被废弃的函数。新的生命周期是:static getDerivedStateFromProps
和getSnapshotBeforeUpdate
。这两组生命周期,不能同时出现,只能存在一组。所以,本文中还是以展示(带UNSAFE_
字样的)传统的生命周期为主。
传统生命周期 | 兼容生命周期 | 新生命周期 |
---|---|---|
componentWillReceiveProps | UNSAFE_componentWillReceiveProps | static getDerivedStateFromProps |
componentWillUpdate | UNSAFE_componentWillUpdate | getSnapshotBeforeUpdate |
新的生命周期,因为理解起来有一定的难度,所以在后续文章中单独开文章描述。
结束语
更多react
的生命周期相关文章,请参考苏南大叔的经验文章。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。