Cherry Studio 中的 useMemo 正确用法:不要在 useMemo 中包裹简单原始类型表达式
发布时间:2026/9/12 3:56:08 锦皓数字建站

Cherry Studio 中的 useMemo 正确用法不要在 useMemo 中包裹简单原始类型表达式【免费下载链接】cherry-studioAI productivity studio with smart chat, autonomous agents, and 300 assistants. Unified access to frontier LLMs项目地址: https://gitcode.com/GitHub_Trending/ch/cherry-studio导读本文解析 Cherry Studio 仓库内 Vercel React Best Practices 技能库中的一条核心性能规则当表达式足够简单、且结果类型是原始值boolean / number / string时不要用useMemo包裹它。文章结合该规则原文、技能库中同属 re-render 优化分类的姊妹规则以及仓库渲染进程的真实源码说明何时该用useMemo、何时该直接计算帮助你写出既正确又高效的 React 组件。规则出处与定位本条规则位于仓库的 .agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md是整个「Vercel React Best Practices」技能库中 62 条规则之一。根据 .agents/skills/vercel-react-best-practices/SKILL.md 中的分类说明该规则属于Re-render Optimization第 5 类文件前缀为rerender-影响等级评估为LOW-MEDIUM低-中等影响描述为「wasted computation on every render」每次渲染都会产生无谓的计算开销。规则文件遵循统一的 frontmatter 结构title/impact/impactDescription/tags并采用「错误示例 正确示例」的对比格式便于 Agent 与 LLM 直接检索引用。规则核心原始类型简单表达式直接计算即可规则原文的判定标准有两层表达式足够简单只包含少量逻辑运算符||、、!或算术运算符、-、*、/、比较运算结果类型是原始值boolean、number或string。当以上两个条件同时满足时不要使用useMemo。原因是调用useMemo本身需要保存上一次的计算结果、在每次渲染时逐一比较依赖数组中的每一项这套「记忆化」机制的固定开销可能比被包裹的那个简单表达式本身还要昂贵。错误示例不推荐function Header({ user, notifications }: Props) { const isLoading useMemo(() { return user.isLoading || notifications.isLoading }, [user.isLoading, notifications.isLoading]) if (isLoading) return Skeleton / // return some markup }这里的问题在于user.isLoading || notifications.isLoading只是一个布尔短路运算本身开销可以忽略但useMemo要求 React 在每次渲染时执行依赖比较即比较user.isLoading与notifications.isLoading两个依赖项是否发生变化如果每次渲染都产生新对象引用依赖比较甚至会失效导致useMemo退化为「每次都重新计算」且额外承担比较成本。正确示例推荐function Header({ user, notifications }: Props) { const isLoading user.isLoading || notifications.isLoading if (isLoading) return Skeleton / // return some markup }直接计算user.isLoading || notifications.isLoading每次渲染都是一次廉价的布尔运算无需任何记忆化机制介入。记忆化的成本模型useMemo 不是免费的要真正理解这条规则需要看清useMemo的完整成本结构。从 React Hooks 的实现机制看每次渲染时useMemo都要经历保存闭包把传入的工厂函数与依赖数组记录下来依赖比较对依赖数组逐项执行Object.is比较可能的重算只有依赖变化时才重新执行工厂函数。也就是说记忆化省下的是「工厂函数重新执行」的成本代价是「每次渲染都要做依赖比较」。当工厂函数本身是a || b、a b、count 0、name.trim()这类微秒级操作时依赖比较的固定成本反而超过了省下的收益——这就是规则评估为 LOW-MEDIUM 影响的原因它属于「增量优化」不会带来质变但写多了会积累出可感知的浪费。同类规则 rerender-dependencies.md 也从另一个角度印证了同一思想依赖应该尽量是原始值、且数量要少。当依赖从对象收窄为原始值时比较成本更低、effect 触发更少。而本条规则更进一步连useMemo本身都不需要。何时才应该用 useMemo与简单表达式的边界「不要在 useMemo 中包裹简单原始表达式」不等于「禁用 useMemo」。同目录下的姊妹规则 rerender-memo.md 明确指出代价高昂的计算才值得提取并记忆化例如const UserAvatar memo(function UserAvatar({ user }: { user: User }) { const id useMemo(() computeAvatarId(user), [user]) return Avatar id{id} / })computeAvatarId(user)这类涉及复杂派生、对象哈希、字符串拼接或深层遍历的计算属于useMemo的合理场景。此外 rerender-lazy-state-init.md 还给出了另一个高频误用点useState(buildSearchIndex(items))会在每次渲染都执行初始化函数应改为useState(() buildSearchIndex(items))的惰性初始化形式。判断边界时可参考以下速查表表达式类型示例是否使用 useMemo简单布尔短路a || b、a !b否直接计算简单算术/比较count 0、total * 2否直接计算字符串拼接/简单格式化#${id}、name.trim()否直接计算昂贵派生遍历、哈希、序列化computeAvatarId(user)、JSON.stringify(data)是配合 memo 组件需要稳定引用传给子组件依赖复杂对象/数组构造是结合依赖数组使用Cherry Studio 源码中的实际应用印证在 Cherry Studio 的渲染进程中useMemo的使用是相当克制的这正好印证了「简单表达式不记忆化」的工程实践。以聊天/编辑器相关的热点渲染路径为例从源码结构看src/renderer/components/composer/ComposerSurfaceRuntime.tsx 等文件中的useMemo调用多用于构造运行时常量、回调集合等引用需要稳定的对象而非包裹简单的布尔/数值派生src/renderer/components/Chart/useChartTheme.ts、src/renderer/components/CodeViewer.tsx 等文件中useMemo的工厂函数都承担了真正的派生工作主题对象构建、代码高亮相关计算而非a || b级别的运算。这种「把 useMemo 留给真正昂贵的派生、让简单原始表达式直接计算」的取舍正是本条规则希望达成的代码形态。对于像 Cherry Studio 这样拥有大量聊天消息、长列表、高频状态更新的客户端应用避免无意义的记忆化既能减少每次渲染的固定开销也能让代码更简洁、更易于阅读与审查。实践检查清单在编写或审查 React 组件时可以按以下顺序自查结果类型是原始值吗boolean / number / string → 进入第 2 步对象 / 数组 / 函数 → 考虑引用稳定性可能需要useMemo/useCallback表达式简单吗只含少量逻辑/算术运算符 → 直接内联计算删除useMemo如果表达式昂贵遍历、序列化、构建索引等→ 才使用useMemo并确保依赖数组是精确的原始值参考 rerender-dependencies.md是否开启了 React Compilerrerender-memo.md 特别提醒若项目启用 React Compilermemo()与useMemo()的手动记忆化通常不再必要编译器会自动优化重渲染怀疑是否误用优先移除useMemo观察表现再考虑反向优化避免过早优化。总结rerender-simple-expression-in-memo这条规则传达的核心是记忆化是有成本的它只应该用在值得记忆化的地方。对于user.isLoading || notifications.isLoading这类简单原始表达式直接计算是最优解把useMemo留给真正昂贵的派生计算才能让组件在每次渲染时都保持最低的开销。在 Cherry Studio 这样的桌面级 AI 生产力应用中这类「小事」在长会话、高频消息流场景下不断累积最终会反映在界面的流畅度上。【免费下载链接】cherry-studioAI productivity studio with smart chat, autonomous agents, and 300 assistants. Unified access to frontier LLMs项目地址: https://gitcode.com/GitHub_Trending/ch/cherry-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。