我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

本文继续说react@18的类式组件的生命周期,这是个比较长的话题,所以分为几部分来说。本文描述组件更新逻辑,组件更新这块,比较容易产生死循环或者无效更新。所以,更加需要清晰的生命周期。本文依然强调说的是react@18的类式组件,无关函数式组件。

苏南大叔:react教程,如何理解类组件生命周期基本逻辑之更新? - 生命周期更新过程
react教程,如何理解类组件生命周期基本逻辑之更新? (图3-1)

大家好,这里是苏南大叔的平行空间笔记本博客,这里记录苏南大叔和计算机代码的故事。本文描述类式组件的“组件更新”所涉及的生命周期。测试环境:create-react-app@5.0.1react@18.2.0react-dom@18.2.0node@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>
    )
  }
}

苏南大叔:react教程,如何理解类组件生命周期基本逻辑之更新? - 测试代码
react教程,如何理解类组件生命周期基本逻辑之更新? (图3-2)

外部组件通过修改props来触发子组件的componentWillReceiveProps生命周期。如下图所示:

苏南大叔:react教程,如何理解类组件生命周期基本逻辑之更新? - 修改props-state
react教程,如何理解类组件生命周期基本逻辑之更新? (图3-3)

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这个是类式组件的一个生命周期,实际上类式组件也存在着两种,分别是PureComponentReact.Component。而shouldComponentUpdatePureComponent是存在冲突的,因为PureComponent本身的定义是可以根据propsstate自动判断是否需要更新组件的。所以,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_componentWillReceivePropsUNSAFE_componentWillUpdate是被废弃的函数。新的生命周期是:static getDerivedStateFromPropsgetSnapshotBeforeUpdate。这两组生命周期,不能同时出现,只能存在一组。所以,本文中还是以展示(带UNSAFE_字样的)传统的生命周期为主。

传统生命周期兼容生命周期新生命周期
componentWillReceivePropsUNSAFE_componentWillReceivePropsstatic getDerivedStateFromProps
componentWillUpdateUNSAFE_componentWillUpdategetSnapshotBeforeUpdate

新的生命周期,因为理解起来有一定的难度,所以在后续文章中单独开文章描述。

结束语

更多react的生命周期相关文章,请参考苏南大叔的经验文章。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react