React Class Component 生命周期执行顺序

132 阅读3分钟

React Class 组件的生命周期可分为 挂载(Mounting)更新(Updating)卸载(Unmounting) 三个阶段。以下是各阶段生命周期方法的执行顺序及核心作用:


一、挂载阶段(Mounting)

当组件实例被创建并插入 DOM 时触发,执行顺序如下:

1. constructor()

  • 作用:初始化 state、绑定方法(如事件处理函数)。
  • 注意:必须调用 super(props),否则 this.props 未定义。
  • 示例
    constructor(props) {
      super(props);
      this.state = { count: 0 };
      this.handleClick = this.handleClick.bind(this);
    }
    

2. static getDerivedStateFromProps(nextProps, prevState)(React 16.3+)

  • 作用:根据新的 props 更新 state
  • 注意:静态方法,无 this 访问权;返回 null 或新的 state 对象。
  • 示例
    static getDerivedStateFromProps(props, state) {
      if (props.value !== state.prevValue) {
        return { prevValue: props.value, derivedValue: props.value * 2 };
      }
      return null;
    }
    

3. render()

  • 作用:生成虚拟 DOM(必须返回 ReactElement、数组、null 等)。
  • 注意:纯函数,不应在此处修改 state 或执行副作用操作。
  • 示例
    render() {
      return <div>{this.state.count}</div>;
    }
    

4. componentDidMount()

  • 作用:组件挂载到 DOM 后执行副作用(如数据请求、订阅事件、操作 DOM)。
  • 示例
    componentDidMount() {
      fetchData().then(data => this.setState({ data }));
      this.timer = setInterval(() => this.tick(), 1000);
    }
    

二、更新阶段(Updating)

当组件的 propsstate 变化时触发,执行顺序如下:

1. static getDerivedStateFromProps(nextProps, prevState)

  • 与挂载阶段相同,用于响应 props 变化更新 state

2. shouldComponentUpdate(nextProps, nextState)

  • 作用:决定是否重新渲染组件(返回 truefalse)。
  • 注意:性能优化关键点,避免不必要的渲染。
  • 示例
    shouldComponentUpdate(nextProps, nextState) {
      return nextProps.id !== this.props.id || nextState.count !== this.state.count;
    }
    

3. render()

  • 生成新的虚拟 DOM,与旧 DOM 对比后更新实际 DOM。

4. getSnapshotBeforeUpdate(prevProps, prevState)(React 16.3+)

  • 作用:在 DOM 更新前捕获信息(如滚动位置),返回值传递给 componentDidUpdate
  • 示例
    getSnapshotBeforeUpdate() {
      return this.listRef.scrollHeight;
    }
    

5. componentDidUpdate(prevProps, prevState, snapshot)

  • 作用:DOM 更新后执行副作用(如基于新 DOM 的操作)。
  • 注意:避免直接调用 setState,否则可能导致无限循环。
  • 示例
    componentDidUpdate(prevProps, prevState, snapshot) {
      if (this.props.userID !== prevProps.userID) {
        this.fetchData(this.props.userID);
      }
      this.listRef.scrollTop = this.listRef.scrollHeight - snapshot;
    }
    

三、卸载阶段(Unmounting)

当组件从 DOM 中移除时触发:

1. componentWillUnmount()

  • 作用:清理副作用(如取消网络请求、清除定时器、移除事件监听)。
  • 示例
    componentWillUnmount() {
      clearInterval(this.timer);
      window.removeEventListener('resize', this.handleResize);
    }
    

四、错误处理(Error Handling)

当子组件抛出错误时触发:

1. static getDerivedStateFromError(error)(React 16+)

  • 作用:捕获子组件错误并更新 state 以显示错误 UI。
  • 示例
    static getDerivedStateFromError(error) {
      return { hasError: true };
    }
    

2. componentDidCatch(error, info)(React 16+)

  • 作用:记录错误信息(如上报到监控系统)。
  • 示例
    componentDidCatch(error, info) {
      logErrorToService(error, info.componentStack);
    }
    

五、已废弃的生命周期方法(避免使用)

  • componentWillMount():已被 constructorcomponentDidMount 替代。
  • componentWillReceiveProps(nextProps):使用 getDerivedStateFromProps 替代。
  • componentWillUpdate(nextProps, nextState):使用 getSnapshotBeforeUpdate 替代。

六、执行顺序流程图

挂载阶段:
constructor → getDerivedStateFromProps → render → componentDidMount

更新阶段:
getDerivedStateFromProps → shouldComponentUpdate → render → getSnapshotBeforeUpdate → componentDidUpdate

卸载阶段:
componentWillUnmount

错误处理:
子组件错误 → getDerivedStateFromError → render → componentDidCatch

七、总结

生命周期方法阶段核心用途
constructor挂载初始化状态和方法绑定
getDerivedStateFromProps挂载/更新根据 props 更新 state
render挂载/更新生成虚拟 DOM
componentDidMount挂载副作用操作(数据请求、订阅)
shouldComponentUpdate更新决定是否重新渲染(性能优化)
getSnapshotBeforeUpdate更新捕获 DOM 更新前的信息
componentDidUpdate更新更新后副作用操作
componentWillUnmount卸载清理副作用(定时器、事件监听)

通过合理利用生命周期方法,可以精准控制组件的渲染逻辑和副作用管理。