
react-use 的 useFirstMountState精准识别组件首次渲染的 Hooks 实现与实战【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-useuseFirstMountState是 react-use 提供的一个轻量级 Hooks用于在组件渲染期间判断当前这次渲染是否为组件挂载后的第一次渲染首次渲染返回true后续所有重渲染均返回false。它常被用于实现首次挂载跳过副作用、仅响应更新之类的逻辑也是 react-use 内部多个高级 Hooks如useUpdateEffect、usePreviousDistinct的基础构件。读完本文你将掌握它的 API 用法、底层实现原理、测试验证方式以及如何在自研 Hook 中复用它。函数签名与返回值const isFirstMount: boolean useFirstMountState();无参数传入返回一个boolean组件首次渲染mount 后的第一次 render时为true之后的任何一次重渲染re-render都为false。注意它不是 state而是一个跟随渲染过程动态计算的布尔值每次渲染时都会根据内部记录重新计算并返回因此可以直接在渲染体包括 JSX 条件表达式中使用且不会因为赋值给变量而触发额外的重渲染。基本用法官方文档给出的典型用法是与useUpdate配合在界面上直观展示当前是否处于首次挂载并通过按钮强制重渲染来观察返回值的变化import * as React from react; import { useFirstMountState } from react-use; const Demo () { const isFirstMount useFirstMountState(); const update useUpdate(); return ( div spanThis component is just mounted: {isFirstMount ? YES : NO}/span br / button onClick{update}re-render/button /div ); };运行流程组件挂载并完成首次渲染isFirstMount为true页面显示 This component is just mounted: YES点击 re-render 按钮useUpdate触发一次重渲染此时isFirstMount变为false页面显示 NO此后无论点击多少次按钮只要组件没有卸载重建返回值始终保持false。其中useUpdate是 react-use 提供的一个强制刷新工具其实现基于useReducer见 src/useUpdate.ts内部维护一个自增计数器updateReducer每调用一次返回(num 1) % 1_000_000从而绕过 React 的浅比较强制组件重渲染。把它和useFirstMountState组合即可方便地在演示与调试中验证首次渲染判定。源码实现原理useFirstMountState的实现极其精简完整源码位于 src/useFirstMountState.tsimport { useRef } from react; export function useFirstMountState(): boolean { const isFirst useRef(true); if (isFirst.current) { isFirst.current false; return true; } return isFirst.current; }其工作原理可以拆解为三步用useRef(true)持久化标志位useRef创建的对象在组件的整个生命周期内保持不变isFirst.current的初始值为true用来标记尚未完成首次渲染判定。首次渲染时翻转标志当isFirst.current为true时先将其置为false再返回true。这一步发生在渲染过程中而不是在useEffect中因此返回值在同一次渲染内即可立即生效可用于决定渲染输出的内容。后续渲染直接返回false因为标志位已在首次渲染时被改写之后每次渲染都会走return isFirst.current分支稳定返回false。关键设计点渲染期写入 ref 而非 setState修改isFirst.current不会触发 React 的重渲染ref 变更不会引起渲染调度因此这个翻转是静默的不会造成额外的性能开销也不会产生无限循环。在渲染体内同步判定返回值不依赖副作用时序useEffect还没执行、DOM 尚未提交时判定结果已经确定这对需要首帧渲染就做出不同展示的场景至关重要。组件卸载重建后重新判定ref 的生命周期与组件实例绑定若组件被卸载后重新挂载会重新初始化为true即新的挂载周期会再次判定为首次渲染。测试验证仓库中为useFirstMountState编写了专门的单元测试见 tests/useFirstMountState.test.ts。测试使用testing-library/react-hooks的renderHook渲染 Hook覆盖了三个关键断言it(should return true on first render and false on all others, () { const hook renderHook(() useFirstMountState()); expect(hook.result.current).toBe(true); hook.rerender(); expect(hook.result.current).toBe(false); hook.rerender(); expect(hook.result.current).toBe(false); });测试语义非常直观Hook 首次渲染后返回值必须为true调用rerender()模拟组件因状态或父组件变化产生的重渲染返回值必须变为false连续多次重渲染后返回值始终保持false不会出现翻转回 true的异常。这三个断言精确对应了 Hook 的核心契约也是你在自己项目中接入该 Hook 后最值得验证的行为。此外测试还确认了useFirstMountState从 react-use 主入口导出且返回值类型为booleanexpect.any(Boolean)保证公开 API 的稳定性。在 react-use 内部的复用场景useFirstMountState不只对外提供能力它还被 react-use 内部多个 Hook 引用是构建只在更新阶段生效逻辑的公共基础设施。通过search源码可以确认以下直接依赖src/useUpdateEffect.tsuseUpdateEffect是跳过首次执行的useEffect。它内部先调用useFirstMountState()获取isFirstMount再在useEffect中判断if (!isFirstMount) return effect()。也就是说首次挂载时副作用被跳过只有后续更新才执行这正是useFirstMountState最典型的生产级用法。src/usePreviousDistinct.ts该 Hook 需要记录与上一次不同的值。在渲染期间它用isFirstMount判断是否首次渲染——首次渲染时不更新prevRef后续渲染中只有当前值与上次记录值经compare比较不相等时才推进prevRef与curRef从而保证返回的永远是与当前值不同的上一个值。src/useStateWithHistory.ts带历史记录与前进/后退能力的useState增强版。它在首次挂载时利用isFirstMount一次性完成历史栈的初始化将初始状态写入history.current、裁剪超过capacity的旧记录、设置初始位置源码注释明确写道只在首次挂载时做状态操作避免重渲染被无意义的计算拖累。从这些复用点可以看出useFirstMountState的定位是面向 Hook 作者的基础原语任何需要区分首次渲染与后续更新的自定义 Hook都可以像上面三个例子一样先调用它拿到判定结果再在副作用或渲染逻辑中分支处理。在自定义 Hook 中的实践模板结合 react-use 内部的实现惯例下面给出一个直接在自定义 Hook 中使用useFirstMountState的模板实现首次挂载不触发、仅更新时触发的副作用import { useEffect } from react; import { useFirstMountState } from react-use; const useUpdateEffect (effect: () void, deps: unknown[]) { const isFirstMount useFirstMountState(); useEffect(() { if (!isFirstMount) { return effect(); } }, deps); };要点说明isFirstMount在渲染期即被确定useEffect闭包捕获的正是本次渲染的正确值首次挂载时effect不执行从第二次渲染依赖变化触发开始执行deps依赖数组照常生效语义与useEffect一致。同理如果你需要在渲染输出层面区分首帧例如首次挂载显示骨架屏、之后显示数据可以直接在 JSX 中根据返回值分支渲染无需引入额外的 state 管理。与其他相关 Hooks 的辨析useFirstMountStatevsuseRendersCountuseRendersCount见 src/useRendersCount.ts每次渲染返回useRef(0).current即一个递增的渲染次数。两者都基于useRef在渲染期记账但语义不同前者回答是不是第一次后者回答已经是第几次。需要精确计数如第 3 次渲染做某事时用useRendersCount只需要布尔判定时用useFirstMountState。useFirstMountStatevsuseMount/useEffectOnceuseMount等生命周期类 Hooks 基于useEffect在挂载后执行一次回调属于副作用时机语义useFirstMountState则是渲染期布尔值可以在渲染体、闭包、条件判断中直接消费两者用途互补而非替代。useFirstMountStatevsuseRef手动实现你也可以用const ref useRef(true)手工维护但useFirstMountState把翻转标志位 返回正确值的细节封装成了语义明确的命名 API配合单元测试保证了契约稳定团队内使用时更易读、更不易出错。小结useFirstMountState返回boolean首次渲染true其余渲染false无参数类型签名见 docs/useFirstMountState.md。其实现仅依赖一个useRef标志位在渲染期同步翻转并返回不触发额外重渲染性能开销几乎为零。官方用法与useUpdate配合可直观演示行为生产级用法是作为基础原语构建useUpdateEffect、usePreviousDistinct、useStateWithHistory等仅更新时生效的能力。引入方式import { useFirstMountState } from react-use;该 Hook 已从 src/index.ts 的主入口统一导出。【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考