ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

open-slide 开发实践:Vercel React 最佳实践之不要在 useMemo 中包裹简单原始表达式

open-slide 开发实践:Vercel React 最佳实践之不要在 useMemo 中包裹简单原始表达式 【免费下载链接】open-slideA slide framework built for agents.项目地址https://gitcode.com/gh_mirrors/op/open-slide点击查看免费下载本篇技术指南讲解 Vercel Engineering 维护的 React/Next.js 性能优化规则之一——不要用useMemo包裹计算结果为原始类型boolean、number、string的简单表达式。在 open-slide 项目的开发中无论是编写幻灯片组件、演示播放器还是编辑器面板这条规则都能帮助你避免在每次渲染中付出无意义的记忆化开销读完本文你将掌握什么该用useMemo、什么不该用的清晰判断标准并能结合仓库源码看到真实项目中useMemo的正确落点。规则出处与定位这条规则出自本仓库内的 Vercel React 最佳实践 Skill这是由 Vercel Engineering 维护、面向 Agent 与 LLM 编写/审查/重构 React 与 Next.js 代码的性能优化指南共 70 条规则、8 大类别。其中 Re-render Optimization重渲染优化类别使用rerender-前缀优先级别为 MEDIUM该类别下共有 15 条规则本规则对应的规则文件是 rerender-simple-expression-in-memo.md。规则的 frontmatter 明确标注了它的影响等级impact:LOW-MEDIUMimpactDescription:wasted computation on every render每次渲染都产生浪费的计算tags:rerender, useMemo, optimization在 Skill 汇总文档 AGENTS.md 的目录结构中它是 Re-render Optimization 类别下的 5.3 节紧邻 5.4 Dont Define Components Inside Components是 Agent 进行自动化重构时应优先参考的一组规则。规则核心简单表达式 原始结果类型 不要 useMemo规则原文的定义非常明确当一个表达式很简单只有少数逻辑或算术运算符且结果类型是原始类型boolean、number、string时不要用useMemo包裹它。调用useMemo并比较 hook 依赖所消耗的资源可能比表达式本身的计算还要多。错误写法Incorrectfunction Header({ user, notifications }: Props) { const isLoading useMemo(() { return user.isLoading || notifications.isLoading }, [user.isLoading, notifications.isLoading]) if (isLoading) return Skeleton / // return some markup }正确写法Correctfunction Header({ user, notifications }: Props) { const isLoading user.isLoading || notifications.isLoading if (isLoading) return Skeleton / // return some markup }为什么useMemo 的成本高于一次逻辑运算这条规则成立的关键在于理解useMemo的真实开销。每次组件渲染时useMemo(factory, deps)都要执行以下几件事调用 hook 本身进入 React 的 Hook 调度、创建/复用 Hook 节点对依赖数组逐项比较对[user.isLoading, notifications.isLoading]中的每一项执行Object.is比较决定是否重算依赖变化时才重新执行 factory 函数。对于一个user.isLoading || notifications.isLoading这样的表达式其本身的执行成本只是两次属性读取加一次逻辑或运算属于纳秒级操作。而useMemo带来的 hook 调度与依赖比较开销在每次渲染中都会发生——即使最终没有重算 factory这笔记忆化基础设施的费用也已经付出。这正好对应规则 frontmatter 中的 impactDescriptionwasted computation on every render每次渲染都浪费计算。简言之用一套相对昂贵的记忆化机制去保护一个几乎不花钱的计算得不偿失。判断标准什么时候 useMemo 才真正有价值要准确执行这条规则需要把表达式是否简单和结果类型是否原始两个维度分开判断。规则本身没有给出机械化的阈值但结合同类规则与仓库源码可以总结出以下判断树应当避免 useMemo 的情形满足其一即不推荐表达式只含少量逻辑/算术运算符如a || b、a b、a b、x 768结果类型是 boolean、number、string 等原始值计算本身没有显著的派生成本也没有引用稳定性需求。仍然值得 useMemo 的情形即使结果类型是原始值只要计算本身昂贵useMemo依然合理。open-slide 仓库的 design-provider.tsx 就是典型例子const dirty useMemo(() { if (!draft || !design) return false; return JSON.stringify(draft) ! JSON.stringify(design); }, [draft, design]);这里的dirty是 boolean原始类型但计算过程是对整个DesignSystem对象执行两次JSON.stringify并做字符串比较这是典型的昂贵派生计算用useMemo缓存结果、避免每次渲染都序列化整个设计对象是完全合理的。同文件的previewCss同理design-provider.tsx它是 string原始类型但需要遍历所有 CSS 变量条目并逐行拼装!important覆盖样式字符串属于非平凡计算。而useMemo最常见的不可替代场景是保持引用稳定性——当结果是一个对象、数组或函数且会被作为依赖传给下游 hook、context 或 memo 组件时player.tsx 用useMemo构建 presenterState 对象因为它是usePresenterChannel广播给演示者窗口的状态快照依赖数组[index, pages.length, blackout, startedAt, stepAggregate]每次变化时才重建对象引用history-provider.tsx 用useMemo构建 HistoryCtx context 值对象保证canUndo/canRedo与回调函数不变时 context 引用稳定避免下游消费者无谓重渲染use-visual-editor.ts 用useMemo汇总视觉编辑器的操作句柄对象snapping、align、distribute、setFrame等让消费者只在这些句柄真正变化时才拿到新引用。这些案例与规则形成互补原始值且计算便宜 → 直接写表达式原始值但计算昂贵 → useMemo 缓存对象/引用类型且需要稳定性 → useMemo 保引用。与相邻规则的联动这条规则并非孤立存在它与 Re-render Optimization 类别下的其他规则共同构成完整的优化判断体系5.6 Extract to Memoized Componentsrerender-memo.md当昂贵工作发生在组件树内部时优先把计算提取到memo()包裹的子组件中让父组件可以提前 return如 loading 时渲染 Skeleton从而跳过整个子树的计算。规则中的反例是useMemo里拼 JSXAvatar id{id} /正确做法是const UserAvatar memo(...)组件级记忆化。这说明组件级memo()负责跳过整段渲染useMemo只负责缓存单个值二者不可混用。5.7 Narrow Effect Dependenciesrerender-dependencies.md与原始结果类型的判断精神一致effect 依赖应尽量收窄为原始值如user.id而非user派生状态如isMobile width 768应放在渲染期间计算而不是放进 effect 触发。这条规则与本规则共同传递一个理念——原始值是最廉价、最稳定的比较单位能直接用原始表达式就不要绕道。实战检查清单在 open-slide 的幻灯片组件、播放器或编辑器中编写代码时可以用这份清单快速自查结果类型是否为 boolean / number / string是 → 进入下一步否对象/数组/函数→ 检查是否需要引用稳定性表达式是否只有少数逻辑或算术运算符是 →直接赋值去掉 useMemo如果计算涉及遍历、序列化、字符串拼装等非平凡开销 → 保留 useMemo并在依赖数组中列出精确的原始依赖如果目标是让子组件跳过重渲染 → 优先考虑memo()组件提取而不是用useMemo缓存 JSX。总结不要在 useMemo 中包裹简单原始表达式是 open-slide 中编写 React 代码时应内化的一条低成本、高可操作性规则user.isLoading || notifications.isLoading这类表达式直接写在渲染函数里既减少每次渲染的 hook 调度与依赖比较开销也让代码更短、更易读。真正值得useMemo的是昂贵计算如JSON.stringify比较和需要引用稳定性的对象值如 context value、广播状态快照open-slide 仓库中的 design-provider.tsx、player.tsx、history-provider.tsx 正是这两类正确场景的参考实现。完整的 70 条规则可进一步查阅 AGENTS.md 与 Skill 说明。赞分享【免费下载链接】open-slideA slide framework built for agents.项目地址https://gitcode.com/gh_mirrors/op/open-slide点击查看免费下载相关推荐DLSS Swapper 完整教程3 步把游戏里的旧版 DLSS/FSR/XeSS 换成新版DLSS Swapper 完整教程3 步把游戏里的旧版 DLSS/FSR/XeSS 换成新版 DLSS Swapper 是一款免费开源的 Windows 桌面桌面应用ZCode 前端性能实践不要在 useMemo 中包裹简单原始值表达式ZCode 前端性能实践不要在 useMemo 中包裹简单原始值表达式 导读 本文基于 ZCode 仓库内置的 Vercel React 性能优化规范 .aCherry Studio 渲染优化实践不要在 useMemo 中包裹简单原始类型表达式Cherry Studio 渲染优化实践不要在 useMemo 中包裹简单原始类型表达式 本篇技术指南源自 Cherry Studio 仓库内 .agents人工智能大模型AI 应用交互助手本地部署上一篇用一份 HTML 简历模板 3 步生成专业 PDF 简历html-resume 完整指南下一篇Open WebUI 完整入门3 步搭建自托管 AI 对话平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表