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

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

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

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

总结

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

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

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

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

相关推荐
夜郎king几秒前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳9 分钟前
JavaScript 的宏任务和微任务
javascript
夏幻灵1 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星1 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_1 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝1 小时前
RBAC前端架构-01:项目初始化
前端·架构
程序员agions1 小时前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发1 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_2 小时前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞052 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl