React 生命周期函数详解

React 组件在其生命周期中有多个阶段,每个阶段都有特定的生命周期函数(Lifecycle Methods)。这些函数允许你在组件的不同阶段执行特定的操作。以下是 React 组件生命周期的主要阶段及其对应的生命周期函数,并结合了 React 16.3+ 的变化。


一、挂载阶段(Mounting)

在组件首次被挂载到 DOM 时会触发的一系列生命周期函数。

  • constructor(props):

    • 初始化组件的状态和绑定事件处理器。
    • 注意:尽量避免在此进行复杂的计算或副作用操作。
    js 复制代码
    constructor(props) {
      super(props);
      this.state = { count: 0 };
      this.handleClick = this.handleClick.bind(this); // 绑定事件处理器
    }
  • static getDerivedStateFromProps(nextProps, prevState):

    • 在组件挂载和更新之前调用,用于根据新的 props 更新 state。
    • 返回一个对象来更新 state,或者返回 null 表示不需要更新。
    js 复制代码
    static getDerivedStateFromProps(nextProps, prevState) {
      if (nextProps.value !== prevState.value) {
        return { value: nextProps.value };
      }
      return null;
    }
  • render():

    • 必须实现的方法,用于渲染组件的虚拟 DOM。
    • 不应该在这里进行副作用操作(如 API 调用、DOM 操作等)。
    js 复制代码
    render() {
      return <div>{this.state.count}</div>;
    }
  • componentDidMount():

    • 组件挂载完成后调用,通常用于发起网络请求、订阅事件等副作用操作。
    js 复制代码
    componentDidMount() {
      fetch('/api/data').then(response => this.setState({ data: response.data }));
    }

二、更新阶段(Updating)

当组件的 props 或 state 发生变化时,会触发一系列更新阶段的生命周期函数。

  • static getDerivedStateFromProps(nextProps, prevState):

    • 同挂载阶段的 getDerivedStateFromProps,用于根据新的 props 更新 state。
  • shouldComponentUpdate(nextProps, nextState):

    • 判断组件是否需要重新渲染。返回 false 可以阻止不必要的重新渲染,从而优化性能。
    js 复制代码
    shouldComponentUpdate(nextProps, nextState) {
      return nextState.count !== this.state.count;
    }
  • render():

    • 同挂载阶段的 render() 方法,用于渲染组件的虚拟 DOM。
  • getSnapshotBeforeUpdate(prevProps, prevState):

    • 在最新的渲染输出提交给 DOM 之前调用,可以捕获一些 DOM 信息(如滚动位置),以便在 componentDidUpdate 中使用。
    js 复制代码
    getSnapshotBeforeUpdate(prevProps, prevState) {
      if (prevProps.items.length < this.props.items.length) {
        return this.listRef.scrollHeight;
      }
      return null;
    }
  • componentDidUpdate(prevProps, prevState, snapshot):

    • 组件更新完成后调用,可以在此进行副作用操作(如网络请求、DOM 操作等)。
    js 复制代码
    componentDidUpdate(prevProps, prevState, snapshot) {
      if (snapshot !== null) {
        this.listRef.scrollTop = this.listRef.scrollHeight - snapshot;
      }
    }

三、卸载阶段(Unmounting)

当组件从 DOM 中卸载时会触发的生命周期函数。

  • componentWillUnmount():

    • 组件卸载和销毁之前立刻调用,通常用于清理工作,如取消网络请求、清除定时器、移除事件监听器等。
    js 复制代码
    componentWillUnmount() {
      clearInterval(this.timerID);
      this.subscription.remove();
    }

四、错误处理阶段(Error Handling)

当组件抛出错误时会触发的生命周期函数。

  • static getDerivedStateFromError(error):

    • 当子组件抛出错误时调用,用于更新 state 以便显示错误 UI。
    js 复制代码
    static getDerivedStateFromError(error) {
      return { hasError: true };
    }
  • componentDidCatch(error, info):

    • 当子组件抛出错误时调用,通常用于记录错误日志或上报错误。
    js 复制代码
    componentDidCatch(error, info) {
      logErrorToService(error, info);
    }

五、React 16.3+ 生命周期变化

随着 React 16.3+ 的发布,部分生命周期函数被废弃或新增了一些新的生命周期函数:

  • 废弃的生命周期:

    • componentWillMount(建议使用 componentDidMount)
    • componentWillReceiveProps(建议使用 static getDerivedStateFromProps)
    • componentWillUpdate(建议使用 getSnapshotBeforeUpdate)
  • 新增的生命周期:

    • getDerivedStateFromProps:用于在挂载和更新前根据 props 更新 state。
    • getSnapshotBeforeUpdate:在最新的渲染输出提交给 DOM 之前调用,捕获一些 DOM 信息。

钩子函数(Hooks)

随着 React Hooks 的引入,许多类组件的生命周期方法可以通过钩子函数来实现:

  • useEffect:

    • 相当于 componentDidMount、componentDidUpdate 和 componentWillUnmount 的组合。
    js 复制代码
    useEffect(() => {
      // 类似 componentDidMount 和 componentDidUpdate
      fetchData().then(data => setState({ data }));
    
      // 清理函数,类似 componentWillUnmount
      return () => {
        cleanup();
      };
    }, [props.userID]); // 依赖项数组
  • useLayoutEffect:

    • 类似 useEffect,但在所有 DOM 变更之后同步调用,适用于需要同步执行的副作用操作。
  • useMemo 和 useCallback:

    • 用于性能优化,类似于 shouldComponentUpdate。

总结

React 组件的生命周期分为三个主要阶段:挂载(Mounting)、更新(Updating)和卸载(Unmounting)。每个阶段都有相应的生命周期函数,帮助开发者在组件的不同生命周期中执行特定的操作。

  • 挂载阶段:初始化状态、渲染组件、发起数据请求等。
  • 更新阶段:判断是否需要重新渲染、捕获 DOM 信息、执行副作用操作等。
  • 卸载阶段:清理资源、取消订阅等。

通过合理使用这些生命周期函数,可以构建出更加健壮和高效的 React 应用程序。同时,现代 React 开发中推荐使用 Hooks 来替代类组件的生命周期方法,以简化代码并提高可维护性。

理解这些生命周期函数及其作用,不仅有助于编写高效且易于维护的 React 组件,还能更好地应对复杂的应用场景。

相关推荐
OpsEye17 分钟前
大模型 Token 计量不准,是什么原因,怎么解决??
javascript·ai编程
梦de天空一米16882 小时前
【一个重复id让游戏卡在62%,聊聊配置表检查】
前端
ryn483982 小时前
01 一个功能模块,怎么分层才不乱
前端·ai编程·claude
Amos_Web2 小时前
通过 Rspack 源码学 Rust(五):读懂 Result 与问号运算符的错误返回
前端
杨航 AI2 小时前
JEV的用法
java·前端·数据库
Amos_Web2 小时前
Rspack 源码解析(三十五):rspack_error 如何用 miette 渲染带源码定位的错误链
前端
去伪存真2 小时前
高敏资产场景下的大模型协同设计架构
前端·agent
修炼的dance2 小时前
OCR预处理测了108组,纠斜去噪有用,坑在顺序和力度
前端
疯华整猫2 小时前
Android 16 后台常驻适配:用 Trae 搭一套“前台服务 + 加急 Job”的可存活架构
前端
独隅2 小时前
WebStorm Windows 版 React / Next.js 实战替换指南
javascript·windows·webstorm