OpenMontage 前端性能实战:遵循 Vercel React 最佳实践,在渲染期间计算派生状态而非依赖 useEffect OpenMontage 前端性能实战遵循 Vercel React 最佳实践在渲染期间计算派生状态而非依赖 useEffect【免费下载链接】OpenMontageWorlds first open-source, agentic video production system. 12 production pipelines, 100 tools, 700 agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage导读本文深入剖析 Vercel React 最佳实践中「在渲染期间计算派生状态Calculate Derived State During Rendering」这一核心规则它属于重渲染优化Re-render Optimization范畴用于消除因冗余 state 与 effect 联动带来的额外渲染和状态漂移state drift。在本仓库中该规则被收录于 .claude/skills/vercel-react-best-practices 与 .agents/skills/vercel-react-best-practices 两个 Agent Skill 目录同一份技能以双份部署并被rerender-前缀下的多条姊妹规则共同支撑。读完本文你将掌握如何识别「可以用派生值取代的冗余 state effect」写出更少重渲染、无状态漂移的 React/Remotion 组件并能将同类审查能力直接应用到本仓库 remotion-composer 的视频合成器前端代码上。规则原文与定位规则文件 rerender-derived-state-no-effect.md 的 frontmatter 明确定义了它的属性--- title: Calculate Derived State During Rendering impact: MEDIUM impactDescription: avoids redundant renders and state drift tags: rerender, derived-state, useEffect, state ---标题在渲染期间计算派生状态影响等级MEDIUM中等收益对应技能体系中的「5. Re-render Optimization」分类影响描述避免冗余渲染与状态漂移标签rerender / derived-state / useEffect / state。在技能的整体分类体系中见 SKILL.md 与 rules/_sections.md8 大分类按优先级排列本规则属于第 5 类「Re-render Optimization重渲染优化」该类别的核心目标描述为Reducing unnecessary re-renders minimizes wasted computation and improves UI responsiveness减少不必要的重渲染以最小化浪费的计算并提升 UI 响应性。规则的核心主张可以用一句话概括如果一个值可以由当前的 props/state 直接计算得出就不要把它存进 state也不要用 effect 去更新它。应当在渲染期间派生出该值从而避免额外渲染和状态漂移。不要仅仅为了响应 prop 变化而在 effect 里 setState应优先使用派生值或使用 keyed resets基于 key 的重置作为替代方案。这条规则与 React 官方文档「You Might Not Need an Effect」一脉相承其本质是effect 应保留给真正需要与外部系统同步的场景订阅、网络请求、DOM 操作等而不应承担「在 state 之间搬运数据」的工作。反模式冗余 state 与 effect 的联动规则文档给出了一段典型反模式代码function Form() { const [firstName, setFirstName] useState(First) const [lastName, setLastName] useState(Last) const [fullName, setFullName] useState() useEffect(() { setFullName(firstName lastName) }, [firstName, lastName]) return p{fullName}/p }这段代码存在的问题可以从三个层面拆解引入了一次额外的渲染fullName被存成 state 后当firstName或lastName变化时React 需要经历「渲染 → 提交 → 触发 effect → 再次 setState → 再次渲染」的完整闭环。也就是说一次用户输入至少要触发两轮渲染而fullName本身在第二轮之前显示的还是一份过期值。存在中间态 / 状态漂移风险在 effect 触发之前的那个渲染帧里fullName仍是旧值UI 会短暂显示与当前输入不一致的内容。在更复杂的场景中例如多个 state 相互派生的链式 effect中间态会进一步放大甚至形成难以追踪的级联更新。依赖数组是隐性契约effect 的正确性完全依赖开发者把[firstName, lastName]写全。一旦将来组件新增了影响fullName计算的第三个输入而忘记更新依赖数组就会产生引用过期 state 的陈旧闭包stale closure——这正是同技能下 rerender-functional-setstate.md 所警告的那类 bug 源头。正解在渲染期间直接派生同一份规则给出了修正版本function Form() { const [firstName, setFirstName] useState(First) const [lastName, setLastName] useState(Last) const fullName firstName lastName return p{fullName}/p }修正后的关键差异在于fullName只是一个普通局部变量在每次渲染时由当前的firstName与lastName同步计算得出。由此获得三方面收益零额外渲染输入变化只需一轮渲染UI 永远与输入状态同步不存在中间帧零状态漂移派生值在数学上恒等于「当前状态的函数」任何时刻渲染结果都与状态严格一致不会出现「状态已变、界面未跟上」的窗口期零依赖数组没有 effect就不存在依赖数组漏写、闭包过期的问题代码心智负担显著降低。派生计算本身需要遵循「轻量」原则——它会在每次渲染时执行因此适用于字符串拼接、布尔判断、数组 filter/map、对象重组等低成本运算如果派生计算开销高昂如大型搜索索引构建则应参考 rerender-memo.md 用useMemo按依赖缓存或参考 rerender-lazy-state-init.md 将一次性重计算放入useState的惰性初始化函数。何时不能直接派生关于 prop 变化重置 state 的替代方案规则明确指出当「派生值」无法表达可修改的受控状态例如表单正在编辑、但尚未提交的半成品数据或需要在 prop 变化时重置一段内部 state时不能简单照搬派生公式。此时规则给出两个替代方案方案一keyed resets基于 key 的重置当某个 state 完全从属于某个 prop 时与其在 effect 里监听 prop 变化后setState不如直接利用 React 的key机制强制重建组件function ProfilePage({ userId }) { return ProfileForm key{userId} / } function ProfileForm({ userId }) { // 每次 userId 变化整个组件被重新挂载内部 state 自动重置 const [draft, setDraft] useState(loadDraft(userId)) // ... }key{userId}让 React 在userId变化时销毁旧组件实例并挂载新实例内部所有useState都天然回到初始值——比「effect 里手动同步 手动重置」更少代码、更少出错机会也彻底消除了「旧 key 的新状态残留在界面上」的漂移窗口。方案二在渲染期间基于上一轮值调整 state若确实需要保留可编辑状态官方推荐的「在渲染期间调整 state」模式同样属于「不用 effect 响应 prop」的范畴。其要点是在渲染函数体内比较上一轮渲染记录的值并在渲染过程中调用 setterReact 会立即用新值重新渲染该组件不会等待 effectfunction List({ items }) { const [prevItems, setPrevItems] useState(items) const [selection, setSelection] useState(null) if (items ! prevItems) { setPrevItems(items) setSelection(null) // 在渲染期间重置派生选择态 } // ... }注意该模式只适用于「在渲染期间调整 state」的场景且应当放在条件分支中、避免无条件 setState 造成无限循环。setPrevItems用于记录基线setSelection完成重置整个过程不经过 effect、不会额外多出一轮提交。联动规则事件里的逻辑不要建模成 state effect与「prop 变化触发 effect」类似的另一种常见反模式是「用户动作建模成 state effect」。姊妹规则 rerender-move-effect-to-event.md 指出如果副作用由具体的用户动作提交、点击、拖拽触发就应当直接写在事件处理器里而不是setState(true) effect 监听。二者同根同源——凡是「值可以算出来」或「动作可以直接执行」的场景都不需要 effect 作为中转站。状态漂移的深层机制「状态漂移」是本规则 impactDescription 的核心词值得展开解释其成因链条当 A 与 B 两个 state 共同派生 C而 C 又被存为 state 时A 或 B 的每一次变化都会让 C 短暂处于「过期」状态直到 effect 补跑如果派生链更长C 派生 DD 派生 E每一环都额外引入一轮渲染与一个中间帧形成级联渲染风暴并发特性如startTransition下过期值甚至可能跨越优先级边界被用户看到产生「界面回跳」依赖数组遗漏时C 会长期停留在旧值上且没有任何编译期报错——这是最隐蔽的漂移。从源码结构看本仓库的 remotion-composer 前端大量采用「渲染期间派生」的模式以 CalloutBox.tsx 为例组件并没有把resolvedBorder、resolvedBg、resolvedIcon存入 state而是在每次渲染时通过const resolvedBorder borderColor || defaults.border这类表达式由 props 与TYPE_DEFAULTS常量直接派生动画值slideX、opacity、scale、borderDraw等也全部由useCurrentFrame()返回的frame在渲染期间通过spring()/interpolate()现算而不是把每一帧写入 state。这正是「能算就不存」原则在视频合成器场景下的直接体现——Remotion 的渲染模型要求每一帧都从当前 frame 派生任何把帧号派生值塞进 state 的做法都会引入多余的提交与中间态。实战自查清单将本规则落地为可执行的审查动作可以在每次写/改 React 组件时对照检查看到useState后先问一句这个值能由现有 props/state 现算出来吗能算就删掉 state直接渲染时派生看到useEffectsetState先问一句这个 effect 是不是仅仅在「把 prop 同步进 state」如果是改用派生值或key重置看到依赖数组就保持警惕依赖数组的存在意味着一段隐式同步契约能删则删区分「派生展示值」与「可编辑受控值」展示性聚合fullName、合计金额、过滤列表一律派生用户可编辑的半成品数据才需要 state派生计算是否轻量每次渲染都会执行重计算请配合useMemo、惰性初始化rerender-lazy-state-init.md或拆分到子组件并用memo隔离rerender-memo.md。在本仓库中的阅读与使用方式本技能在仓库内以两份镜像部署内容一致分别面向不同 Agent 工具链加载Claude 工具链入口.claude/skills/vercel-react-best-practices/SKILL.md其元数据声明license: MIT、author: vercel、version: 1.0.0共收录 65 条规则、覆盖 8 大分类其他 Agent 工具链入口.agents/skills/vercel-react-best-practices/SKILL.md规则全文本规则位于.claude/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md与.agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md同类「重渲染优化」规则rerender-前缀下共 15 条覆盖派生状态订阅rerender-derived-state.md、事件内联、函数式 setState、惰性初始化、useDeferredValue、临时值放 ref 等互补场景可在审查时整组对照。当你在本仓库的 remotion-composer/src/components 下编写或评审新的 React 组件时可直接以本规则作为性能与正确性的双重标准凡是能从当前 frame、props、现有 state 计算出来的值一律在渲染期间派生effect 只留给真正需要与外部系统同步的工作。这既符合 Vercel 工程团队的审查口径也与 Remotion 声明式渲染模型天然契合。【免费下载链接】OpenMontageWorlds first open-source, agentic video production system. 12 production pipelines, 100 tools, 700 agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考