useEffect执行时机踩坑终极解:react-custom-hooks的useEffectOnce与useUpdateEffect实战
2026/8/23 14:30:04 网站建设 项目流程

useEffect执行时机踩坑终极解:react-custom-hooks的useEffectOnce与useUpdateEffect实战

【免费下载链接】react-custom-hooksReact Custom Hooks @ S.Leschev: useArray useAsync useClickOutside useCookie useCopyToClipboard useDarkMode useDebounce useDebugInformation useDeepCompareEffect useEffectOnce useEventListener useFetch useGeolocation useHover useLongPress useMediaQuery useOnlineStatus useOnScreen usePrevious useRenderCount useScript etc.项目地址: https://gitcode.com/gh_mirrors/re/react-custom-hooks

写 React 组件时,你是否也踩过这样的坑:useEffect在组件挂载时就会执行一次,可你只想在它“变化”之后才响应,结果得手写一堆isMounted标记;或者你只想在挂载时执行一次逻辑,却总担心依赖数组写错。开源项目react-custom-hooks提供了 20+ 个生产级自定义 Hook,其中的useEffectOnceuseUpdateEffect两个轻量 Hook,正好一次性解决 useEffect 执行时机的两大高频痛点:🎯

一、useEffect 执行时机,为什么容易踩坑?

先回顾一下useEffect的默认行为,这也是坑的来源:

场景你的期望useEffect 的实际行为
只想挂载时初始化只跑 1 次依赖数组必须写空[],写错就反复执行
只关心数据变化跳过首次首次渲染也会执行,需要手写标记变量

而 react-custom-hooks 的思路很简单:把这些“重复的防御性写法”封装成两个开箱即用的 Hook,一行调用替代一堆样板代码。

二、三步拿到代码,跑通官方 Demo

1️⃣ 克隆仓库:

git clone https://gitcode.com/gh_mirrors/re/react-custom-hooks cd react-custom-hooks npm install && npm start

2️⃣ 打开 src/App.js,取消注释对应演示组件即可切换示例;

3️⃣ 本项目使用 React 18 + CRA,无需任何额外配置,npm start后浏览器直接体验。

三、useEffectOnce:挂载时只执行一次,告别空依赖数组

useEffectOnce的完整实现只有 3 行,位于 useEffectOnce.js:

export default function useEffectOnce(cb) { useEffect(cb, []) }

它的价值在于语义自解释——代码评审时看到useEffectOnce(() => initLibrary()),一眼就知道“这段逻辑只在挂载时跑一次”,而不需要再去核对某个空数组是否正确。

官方演示组件 EffectOnceComponent.js 中,组件挂载时弹出一句 "Hi",之后无论计数器怎么自增都不会再次触发,非常适合作为你的上手示例。

典型使用场景:

  • 初始化第三方图表 / 地图库
  • 拉取初始数据、埋点上报
  • 注册全局事件监听

四、useUpdateEffect:跳过首次渲染,只响应后续变化

如果说useEffectOnce解决“只要第一次”,那useUpdateEffect就解决“只要后面每一次”。它的实现同样简洁,核心是一个 ref 标记,源码见 useUpdateEffect.js:

export default function useUpdateEffect(callback, dependencies) { const firstRenderRef = useRef(true) useEffect(() => { if (firstRenderRef.current) { firstRenderRef.current = false return } return callback() }, dependencies) }

用法和useEffect完全一致,多出来的行为只有“跳过第一次”:

// 跳过首次渲染,仅在 count 后续变化时执行 useUpdateEffect(() => { console.log("count 更新为:", count) }, [count])

官方示例 UpdateEffectComponent.js 演示了点击 Increment 按钮后才弹出最新值,首次渲染保持静默——这正是“监听变化”类需求的正确姿势。

典型使用场景:

  • 数据变化后同步 URL 参数
  • 依赖变化时重新订阅外部服务
  • 避免首屏发出一次多余的“无意义”请求

五、一张表学会选型:什么时候用哪个?

Hook首次挂载依赖变化后一句话总结
useEffect✅ 执行✅ 执行默认选择
useEffectOnce✅ 执行❌ 不执行只要“出生礼”
useUpdateEffect❌ 跳过✅ 执行只要“成长史”

六、实战避坑小贴士

  • 开发模式下的“双重执行”是正常的:本项目 src/index.js 启用了React.StrictMode,开发环境中所有 effect 会被故意挂载两次用于暴露不纯的副作用,这是 React 官方行为,生产构建不会出现,不必误判为 Bug。
  • 配合防抖更丝滑:变化监听类 effect 常和 useDebounce.js 组合使用,避免高频变化触发密集副作用。
  • 排查“到底渲染了几次”:用 useRenderCount.js 实时显示渲染次数,配合 useDebugInformation.js 定位不必要的重渲染。
  • 深度依赖比较:当依赖是对象且浅比较失效时,可升级使用 useDeepCompareEffect.js。

写在最后

useEffect 执行时机的问题,本质上只是 React 没有内建“只挂载 / 只更新”两种模式。react-custom-hooks 用两个不到 15 行的 Hook 就把这套心智模型补齐了:记住口诀——挂载一次找useEffectOnce,跳过首次找useUpdateEffect,你的 effect 代码会立刻清爽一个量级。💪

【免费下载链接】react-custom-hooksReact Custom Hooks @ S.Leschev: useArray useAsync useClickOutside useCookie useCopyToClipboard useDarkMode useDebounce useDebugInformation useDeepCompareEffect useEffectOnce useEventListener useFetch useGeolocation useHover useLongPress useMediaQuery useOnlineStatus useOnScreen usePrevious useRenderCount useScript etc.项目地址: https://gitcode.com/gh_mirrors/re/react-custom-hooks

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询