React Hooks 生命周期

152 阅读3分钟

在 React 中,类组件通过 componentDidMountcomponentDidUpdatecomponentWillUnmount 等方法管理生命周期,而函数组件则通过 Hooks 实现类似的生命周期逻辑,其中最核心的是 useEffect

Taimili 艾米莉 ( 一款免费开源的 taimili.com )

艾米莉 是一款优雅便捷的** GitHub Star 管理和加星工具**,基于 PHP & javascript 构建, 能对github 的 star fork follow watch 管理和提升,最适合github 的深度用户

核心逻辑:Hooks 如何映射生命周期?

函数组件没有类组件那样的「生命周期方法」,而是通过 副作用(Side Effect)  来处理生命周期相关的逻辑(如数据请求、订阅、DOM 操作等)。useEffect 是处理副作用的主要 Hook,它可以模拟类组件的多个生命周期阶段。

1. 挂载阶段(Mount):组件首次渲染完成

对应类组件的 componentDidMount,即组件首次渲染到 DOM 后执行的逻辑(如初始化数据请求、事件监听等)。

实现方式useEffect 传入一个副作用函数,第二个参数传空依赖数组 [] ,表示该副作用只在组件挂载时执行一次。

jsx

useEffect(() => {
  // 组件挂载时执行(类似 componentDidMount)
  console.log("组件挂载完成");
  // 示例:发起初始化请求
  fetchData();
}, []); // 空依赖数组 → 只在挂载时执行

2. 更新阶段(Update):组件重新渲染

对应类组件的 componentDidUpdate,即组件因 props 或 state 变化重新渲染后执行的逻辑(如根据新 props 重新请求数据)。

实现方式

  • 若 useEffect 不传入第二个依赖参数,则每次组件渲染(包括首次和更新)后都会执行,相当于 componentDidMount + componentDidUpdate

  • 若传入非空依赖数组 [dep1, dep2] ,则只有当依赖项(dep1dep2)发生变化时,才会在更新后执行。

jsx

// 1. 每次渲染后都执行(不推荐,可能导致性能问题)
useEffect(() => {
  console.log("组件渲染/更新完成");
});

// 2. 只有当 count 变化时,才在更新后执行(类似 componentDidUpdate)
useEffect(() => {
  console.log(`count 变为 ${count},执行更新逻辑`);
  // 示例:根据新的 count 请求数据
  fetchDataByCount(count);
}, [count]); // 依赖 count → 仅 count 变化时执行

3. 卸载阶段(Unmount):组件从 DOM 中移除

对应类组件的 componentWillUnmount,即组件卸载前需要清理的逻辑(如取消订阅、清除定时器、取消请求等)。

实现方式useEffect 的副作用函数可以返回一个「清理函数」,该函数会在组件卸载时执行,也会在「下一次副作用执行前」执行(避免残留副作用)。

jsx

useEffect(() => {
  // 挂载时执行:开启定时器
  const timer = setInterval(() => {
    console.log("定时器执行中...");
  }, 1000);

  // 返回清理函数(卸载时执行)
  return () => {
    // 组件卸载时清理:清除定时器
    clearInterval(timer);
    console.log("组件卸载,清理完成");
  };
}, []); // 空依赖 → 清理函数仅在卸载时执行

其他 Hooks 与生命周期的关联

  • useLayoutEffect:与 useEffect 用法完全一致,但执行时机不同。useLayoutEffect 在 DOM 更新同步完成后立即执行(阻塞渲染),而 useEffect 在 DOM 更新后异步执行(不阻塞渲染)。适合需要立即操作 DOM 并获取布局信息的场景(类似 componentDidMount 的同步版本)。
  • useMemo / useCallback:用于缓存计算结果或函数,避免不必要的重复计算 / 创建,间接优化更新阶段的性能(类似 shouldComponentUpdate 的部分功能,但逻辑不同)。

总结:Hooks 生命周期的核心特点

  1. 统一抽象:用 useEffect 统一处理挂载、更新、卸载的副作用逻辑,替代类组件中多个生命周期方法的分散实现。

  2. 依赖驱动:通过依赖数组精确控制副作用的执行时机,减少不必要的重复执行。

  3. 清理机制:内置清理函数,自动处理副作用的「收尾工作」,避免内存泄漏。

这种设计让函数组件的逻辑组织更灵活,尤其在处理多个独立副作用时(如同时管理定时器和数据订阅),比类组件的生命周期方法更清晰。