关于 react
这项 React 技能为使用 React 19.2 和 React Compiler 1.0 的开发者提供指导。内容侧重适配编译器的组件与 Hook 写法,并按实现任务组织参考资料。
主要功能
- 01适配 React Compiler 的编码指导
- 02Memoization 决策建议
- 03纯函数与不可变性规则
- 04按任务组织的参考资料
- 05React 19 API 与测试指导
适用场景
- 01编写或审查组件和 Hook
- 02配置编译器与 lint 规则
- 03判断是否保留手动 memoization
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pedronauck/ skills --skill react安装后在 Claude Code 中输入/react确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/compiler-setup.mdcompiler.mdcomponents-and-types.mdeffects.mdreact19-apis.mdrules-of-react.mdstate.mdtesting.md详细介绍
React
面向 React 19.2 和 React Compiler 1.0(babel-plugin-react-compiler),并由 eslint-plugin-react-hooks 7.1+ 检查代码。请阅读与所改动的 API 或行为对应的参考文档。只有在改动涉及相邻领域时才加载相关参考文档;复用已经阅读过的相关上下文。
编译器就是优化器
编译器会在构建时为每个组件应用相当于 memo 的优化,并缓存组件和 Hook 中的计算结果。它的粒度比手写 Hook 更细——甚至能在提前返回之后进行缓存,而这种位置在结构上不允许使用 useMemo。
代价是,React 规则不再只是风格建议,而是构建时契约。组件违反这些规则时,编译器会放弃优化:它会静默跳过该组件并继续处理。构建仍然成功,测试仍然通过,而该组件却始终没有得到优化。请编写不会让编译器放弃优化的代码。
这会带来两个与编译器出现前习惯相反的结论:
- 对开销很小的值习惯性使用
useMemo/useCallback现在只是噪音;而且,依赖数组不完整,比完全不缓存更糟糕——编译器无法匹配手动缓存时,就会拒绝优化该组件。 - 违反规则只会悄然导致优化失效,而不会报错,因此 lint 规则是避免应用在不知不觉中未经优化的唯一保障。启用编译器之前,先启用这些规则。
先决定是否需要缓存
| 情况 | 做法 |
|---|---|
| 新值或回调仅供渲染/JSX 使用 | 直接编写;编译器会为其缓存 |
值作为 useEffect(或其他 Hook)的依赖数组成员,且必须保持标识不变 | 保留 useMemo/useCallback——这是 react.dev 明确指出的逃生口 |
值传给未编译的使用方(原生库实例、addEventListener、未编译的包) | 保留手动缓存 |
| 因任何原因保留的手动缓存 | 确保依赖项完整,否则组件会放弃优化 |
| 现有代码中正常工作的缓存 | 保留——移除它会改变编译输出;动手之前先测试 |
| 多个组件重复执行同一个开销很大的调用 | 编译器的缓存仅限单个组件,不会共享;将调用提升到模块级缓存或数据层 |
| 普通模块级工具函数中的开销很大的工作 | 不会缓存;编译器只覆盖组件和 Hook |
带自定义 areEqual 比较函数的 memo() | 保留;编译器无法实现同等功能 |
完成标准: 本任务新增或修改的每处缓存都能对应到上表中的某一行,且没有为了满足任何一行而添加编译器已经覆盖的 Hook。
参考文档
| 当你…… | 参考文档 |
|---|---|
| 编写或审查任意组件或 Hook 的主体——纯函数性、变更、ref、全局变量 | references/rules-of-react.md |
移除、保留或讨论 useMemo/useCallback/memo,或组件被编译器跳过 | references/compiler.md |
| 安装或配置编译器、lint 预设,或逐步采用编译器 | references/compiler-setup.md |
考虑使用 useEffect,或派生/同步状态 | references/effects.md |
| 设计组件、组合方式、props 或 TypeScript 类型 | references/components-and-types.md |
| 选择状态的存放位置,连接 context 或外部 store | references/state.md |
使用 use()、Actions、useOptimistic、<Activity>、元数据或其他 React 19 API | references/react19-apis.md |
| 编写或修复组件/Hook 测试 | references/testing.md |
应用与所改行为相关的技术规则。
Tripwires
纯度 — 渲染仅根据 props、state 和 context 计算。Math.random()、Date.now()、new Date()、crypto.randomUUID() 和 performance.now() 应放在 state 初始化器、事件处理程序或 effect 中。
变更 — props、state、hook 参数、hook 返回值,以及任何已传给 JSX 的值都是只读的;修改前先复制(setItems([...items].sort()))。在本次渲染中创建且不会逸出的值,可以随意修改。
重新赋值 — 将解构出来的 prop 视为只读:解构时重命名({ value: valueFromProps }),并派生一个新的 const。
Refs — 在 effects 和事件处理程序中读取和写入 ref.current。渲染期间唯一允许的操作是一次性延迟初始化:if (ref.current === null) ref.current = …。
全局变量 — 模块作用域用于存放常量;每次渲染的值放在 useState/useContext 中,向外部写入则放在 effect 中。在渲染期间操作计数器、数组和临时缓存,会破坏 Fast Refresh 并导致无法编译。
组件是静态的 — 在模块作用域声明组件和 hooks。在另一个组件内部定义组件(或从工厂函数返回组件),会导致每次渲染都创建新类型,从而重置 state 并卸载 DOM。
Effects — effect 用于与 React 之外的事物同步。在 effect 中同步调用 setState 来派生或复制 state,属于错误级 lint 违规;应改为在渲染期间计算。
错误 — 子组件渲染错误由 Error Boundary 捕获,绝不能用 JSX 外部的 try/catch 捕获。
Refs 是 props — 在 19 中,forwardRef 已弃用;应在 props 类型中接受 ref。同理,使用 <Context value={…}>,而不是 <Context.Provider>。
逃生舱口 — "use no memo" 是一种二分工具,需要附带书面说明和移除计划,而不是修复方案。
相关技能
TanStack Query、Router 和 Form 使用 tanstack。@xstate/store 使用 xstate-store。组件原语和 CVA 变体使用 shadcn。样式使用 tailwindcss。references/testing.md 之外的运行器配置使用 vitest。