React 组件生命周期指的是一个组件从创建到销毁的过程中的一系列方法。React 提供了一些特殊的生命周期方法来控制组件的行为,特别是在组件的渲染、更新和销毁阶段。生命周期方法对于类组件尤其重要,因为它们帮助开发者执行副作用操作(如数据请求、订阅等)以及处理性能优化。

从 React 16.3 版本开始,生命周期方法进行了更新,并且一些旧的生命周期方法(如 componentWillMountcomponentWillReceivePropscomponentWillUpdate)被标记为不推荐使用。

目录

  1. 生命周期概述
  2. 挂载阶段
  3. 更新阶段
  4. 卸载阶段
  5. 不推荐的生命周期方法
  6. 生命周期与 Hooks
  7. 参考资料

1. 生命周期概述

React 组件生命周期可以分为三个阶段:

  1. 挂载阶段:组件被创建并插入到 DOM 中。
  2. 更新阶段:组件接收到新的 props 或 state 时更新。
  3. 卸载阶段:组件从 DOM 中移除时执行清理工作。

1.1 生命周期方法流程

  • 挂载阶段
    • constructor
    • getDerivedStateFromProps
    • render
    • componentDidMount
  • 更新阶段
    • getDerivedStateFromProps
    • shouldComponentUpdate
    • render
    • getSnapshotBeforeUpdate
    • componentDidUpdate
  • 卸载阶段
    • componentWillUnmount

2. 挂载阶段

当组件被创建并插入到 DOM 时,会经历挂载阶段。这个阶段中会调用以下生命周期方法:

2.1 constructor(props)

constructor 方法是类组件的构造函数,用于初始化状态(state)和绑定事件处理方法。它是挂载阶段的第一个方法,在 render 之前调用。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { counter: 0 };
  }
  
  render() {
    return <div>{this.state.counter}</div>;
  }
}

2.2 getDerivedStateFromProps(props, state)

getDerivedStateFromProps 是一个静态方法,在每次组件接收到新的 props 时调用,允许你根据 props 更新组件的 state。该方法返回一个对象来更新 state,或者返回 null 表示没有状态更新。

class MyComponent extends React.Component {
  static getDerivedStateFromProps(nextProps, nextState) {
    if (nextProps.value !== nextState.value) {
      return { value: nextProps.value };
    }
    return null;
  }

  render() {
    return <div>{this.state.value}</div>;
  }
}

2.3 render()

render 是类组件的唯一必需方法,它返回要渲染的 JSX 或 null(如果没有内容要渲染)。render 方法不能直接修改组件的 stateprops,它是纯粹的呈现方法。

class MyComponent extends React.Component {
  render() {
    return <div>Hello, {this.props.name}</div>;
  }
}

2.4 componentDidMount()

componentDidMount 在组件挂载后调用,它常用于初始化操作,比如数据请求、DOM 操作等。此方法只会在组件第一次挂载时调用一次。

class MyComponent extends React.Component {
  componentDidMount() {
    console.log('Component mounted');
  }

  render() {
    return <div>Hello, World!</div>;
  }
}


3. 更新阶段

更新阶段发生在组件的 propsstate 发生变化时,React 会重新渲染组件。更新阶段的生命周期方法允许开发者控制何时重新渲染组件以及如何优化性能。

3.1 getDerivedStateFromProps(props, state)

getDerivedStateFromProps 在组件每次接收到新的 props 时调用,它是一个静态方法,不依赖于实例 this。如前所述,这个方法用于根据新的 props 更新 state

3.2 shouldComponentUpdate(nextProps, nextState)

shouldComponentUpdate 用于控制组件是否应该重新渲染。该方法接收新的 propsstate,返回一个布尔值,若返回 false,组件不会重新渲染。常用于性能优化。

class MyComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.value !== this.props.value) {
      return true;
    }
    return false;
  }

  render() {
    return <div>{this.props.value}</div>;
  }
}

3.3 render()

和挂载阶段一样,render 方法在更新阶段会被调用,它负责根据新的 propsstate 返回新的 JSX。render 方法会根据 shouldComponentUpdate 的返回值决定是否继续执行。

3.4 getSnapshotBeforeUpdate(prevProps, prevState)

getSnapshotBeforeUpdate 在更新后但渲染前调用,它的返回值会传递给 componentDidUpdate。常用于获取更新前的 DOM 状态(如滚动位置)并用于更新操作。

class MyComponent extends React.Component {
  getSnapshotBeforeUpdate(prevProps, prevState) {
    return null;
  }

  render() {
    return <div>Content</div>;
  }
}

3.5 componentDidUpdate(prevProps, prevState, snapshot)

componentDidUpdate 在组件更新后调用,可以通过此方法访问更新前的 propsstate,适合进行副作用操作,如发送网络请求。

class MyComponent extends React.Component {
  componentDidUpdate(prevProps, prevState) {
    if (this.props.value !== prevProps.value) {
      console.log('Value changed');
    }
  }

  render() {
    return <div>{this.props.value}</div>;
  }
}


4. 卸载阶段

组件从 DOM 中移除时,会调用卸载阶段的生命周期方法。此时我们可以执行清理工作,例如清除定时器或取消订阅等操作。

4.1 componentWillUnmount()

componentWillUnmount 在组件卸载之前调用,适用于清理工作,如清除定时器、取消事件监听等。

class MyComponent extends React.Component {
  componentWillUnmount() {
    console.log('Component will unmount');
  }

  render() {
    return <div>Component</div>;
  }
}


5. 不推荐的生命周期方法

React 16.3 之后,以下生命周期方法已被标记为 不推荐使用,并建议开发者使用新的生命周期方法或 getDerivedStateFromPropsstatic getSnapshotBeforeUpdate 替代。

  • componentWillMount:在组件挂载之前调用,应该使用 constructorgetDerivedStateFromProps 代替。
  • componentWillReceiveProps:在接收到新的 props 时调用,应该使用 getDerivedStateFromProps 替代。
  • componentWillUpdate:在组件更新之前调用,应该使用 getSnapshotBeforeUpdate 替代。

6. 生命周期与 Hooks

在 React 16.8 版本引入了 Hooks,使得函数组件也可以使用类似生命周期的方法,如 useEffect 代替 componentDidMountcomponentDidUpdatecomponentWillUnmount

useEffect

useEffect 用于处理副作用,它在组件挂载、更新和卸载时执行。通过设置依赖项数组,可以控制副作用何时执行。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('Component mounted or updated');

    return () => {
      console.log('Component will unmount');
    };
  }, []); // 空数组表示只在挂载和卸载时调用

  return <div>My Component</div>;
}


7. 参考资料

出站链接

站内链接


React 组件生命周期是理解和优化 React 应用的重要部分,特别是在类组件中。随着 Hooks 的引入,函数组件在处理副作用和生命周期管理方面变得更加灵活和强大。