react 训练通关生命周期

152 阅读4分钟

生命周期

生命周期更改点

react16.4后被替换生命周期

在React16.3之前,由于开发者时常在componentWillMount中进行异步请求,而该方法会被多次调用,导致性能开销过大,官方将三类生命周期方法已被标记为不推荐使用(UNSAFE):

UNSAFE_componentWillMount
UNSAFE_componentWillReceiveProps
UNSAFE_componentWillUpdate

截至最新版本,React并没有完全废除这些UNSAFE的方法,但强烈建议开发者避免使用它们,并使用新的生命周期方法来替代,这样做的目的是为了更好地支持React未来的异步渲染特性。

  • componentWillMount() : 在组件挂载之前调用,通常不推荐使用。
  • componentWillReceiveProps(nextProps) : 当组件接收到新的props时调用,已被getDerivedStateFromProps替代。
  • componentWillUpdate(nextProps, nextState) : 在组件更新之前调用,已被getSnapshotBeforeUpdate替代。

react16.3以前的生命周期

  1. react16.3以前的生命周期:
    主要分为 初始化阶段更新阶段卸载组件

     1.初始化阶段
     constructor->componentWillMount->render->componentDidMount
     
     2.更新阶段
     componentWillReceiveProps->shouldComponentUpdate->componentWillUpdate->
     render->componentDidUpdate
     
     3.卸载组件
     componentWillUnmount
    

image.png

16.4及以后的生命周期

  1. react16.4及以后三个阶段主要有以下改变

     1.创建阶段
     constructor---->getDerivedStateFromProps---->render---->componentDidMount
    
     2.更新阶段
     getDerivedStateFromProps---->sholdComponentUpdate--->render---->getSnapshotBeforeUpdate
     --->componentDidupdate
    
     3.阶段
     componentWillUnmount
    

image.png

生命周期阶段的作用
  1. 挂载阶段 (Mounting)

在这个阶段,组件被创建并插入到DOM中。生命周期方法的调用顺序如下:

  • constructor() : 初始化组件的状态和绑定事件处理方法。此方法在组件挂载之前调用。
  • getDerivedStateFromProps(nextProps, prevState) : 在每次渲染之前调用,用于根据新的props更新state。它是一个静态方法,不能访问this
  • render() : 渲染组件的UI。每次组件更新都会调用此方法。
  • componentDidMount() : 组件挂载完成后调用,适合进行DOM操作和网络请求。
  1. 更新阶段 (Updating)

当组件的props或state发生变化时,会触发更新阶段。生命周期方法的调用顺序如下:

  • getDerivedStateFromProps(nextProps, prevState) : 与挂载阶段相同,在更新时也会调用。
  • shouldComponentUpdate(nextProps, nextState) : 决定组件是否需要重新渲染,返回truefalse
  • render() : 再次渲染组件的UI。
  • getSnapshotBeforeUpdate(prevProps, prevState) : 在最近一次渲染输出之前调用,可以捕获一些信息(如滚动位置)。
  • componentDidUpdate(prevProps, prevState, snapshot) : 组件更新后调用,适合进行DOM操作或网络请求。
  1. 卸载阶段 (Unmounting)

当组件从DOM中移除时,会调用以下方法:

  • componentWillUnmount() : 组件卸载之前调用,适合清理定时器或取消网络请求等。
import React from "react";

class LifecycleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    console.log("Constructor");
  }

  static getDerivedStateFromProps(props, state) {
    console.log("getDerivedStateFromProps");
    return null;
  }

  componentDidMount() {
    console.log("componentDidMount");
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate");
    return true;
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log("getSnapshotBeforeUpdate");
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log("componentDidUpdate");
  }

  componentWillUnmount() {
    console.log("componentWillUnmount");
  }

  handleClick = () => {
    this.setState((prevState) => ({ count: prevState.count + 1 }));
  };

  render() {
    console.log("render");
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick}>Increment</button>
      </div>
    );
  }
}

export default LifecycleComponent;

函数组件生命周期替代方案

useEffect((params) => {
  return params;
}, dep);
  1. useEffect拥有两个参数
    1.1 第一个参数callback,会返回一个清理函数,用于清理副作用。
    1.2 第二参数为可选依赖项dep,用于控制副作用函数的执行时机

  2. useEffect 执行为异步执行,每次该函数执行后,会将useEffect的第一参数callback()放入任务队列中,等到主线程任务完成,包括DOM 更新,js 执行完成,视图绘制后,在进行callback()的执行。
//当useEffect依赖项为空数组时,
useEffect(() => {
  //  请求数据,事件监听,订阅和取消订阅,操纵dom,定时器等操作
  console.log("组件挂载完成:componentDidMount");
  return function componentWillUnmount() {
    /* 解除事件监听器 ,清除 */
    console.log("组件销毁:componentWillUnmount");
  };
}, []);

//当useEffect依赖项为某个变量时,此时可监听,该变量的变化
useEffect(() => {
  console.log("props变化:componentWillReceiveProps");
}, [props]);

// 无依赖项时,可模拟组件更新
useEffect(() => {
  console.log(" 组件更新完成:componentDidUpdate ");
});
生命周期注意点:
  1. 避免在constructor中进行副作用操作,constructor主要用于初始化state和绑定方法,不应该在这里进行网络请求等副作用操作。
  2. 不要在componentWillMount中进行异步操作,componentWillMount在React 16.3后被废弃,且可能会多次调用,不适合进行异步操作。
  3. 不要在render中修改state,render应该是一个纯函数,不应该有副作用。
  4. 在componentDidUpdate中注意条件判断,为避免无限循环,在这里更新state时必须加条件判断。
  5. 在componentWillUnmount中清理资源,取消网络请求、清除定时器等清理工作应在此进行。
  6. 使用错误边界(Error Boundaries)处理错误,通过componentDidCatch或static getDerivedStateFromError来捕获和处理错误。