关于 react
面向 AI Agent 的 React 19 实践指南,涵盖组件开发与结构化代码库审查,包含九类共 49 条规则。
主要功能
- 01九类共 49 条规则
- 02React 19 模式与 API
- 03模式识别示例
- 04结构化多文件审查流程
- 05代码库卫生检查
适用场景
- 01编写或重构 React 组件
- 02将项目从 React 18 迁移到 React 19
- 03审查 React 仓库中的性能与设计问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pproenca/ dot-skills --skill react安装后在 Claude Code 中输入/react确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdmetadata.jsonassets/templates/_template.mdreferences/_review-algorithm.md_sections.mdconc-activity-component.mdconc-automatic-batching.mdconc-concurrent-safe.mdconc-suspense-fallback.mdconc-use-deferred-value.mdconc-use-transition.mdcross-boundary-coherence.mdcross-component-consolidation.mdcross-dead-code.mdcross-extract-shared-logic.mdcross-prop-shape-drift.mddata-cache-deduplication.mddata-document-metadata.mddata-error-boundaries.mddata-parallel-fetching.mddata-resource-hints.mddata-suspense-data-fetching.mddata-use-hook.mdeffect-avoid-unnecessary.mdeffect-cleanup.mdeffect-object-dependencies.mdeffect-use-effect-event.mdeffect-use-sync-external-store.mdform-actions.mdform-use-action-state.md详细介绍
React 19 最佳实践
面向 AI Agent 的 React 19/19.2 最佳实践综合指南。包含 9 个类别中的 49 条规则,按影响从关键(并发渲染、服务端组件)到贯穿整个代码库的代码卫生(去重、死代码、边界一致性)排序。涵盖 React 19 的主要更新:ref 作为常规属性(弃用 forwardRef)、原生文档元数据、资源预加载 API、useActionState、useOptimistic、use() Hook,以及作为 Provider 的 <Context>。
规则文件描述的是模式形态(而非 API 名称),并以 “需要识别的形态” 一节开篇,列出同一种问题可能呈现的 2–4 种语法伪装。精选高价值规则(其伪装形态在实际代码库中最常见,包括表单 Action、ref 作为属性、派生状态、Context、use() Hook、useCallback/memo 配对)还包含一组具体的 “伪装案例” 错误/正确示例,用于教你识别 grep 难以发现的模式。
何时应用
- 编写新的 React 组件或重构现有组件
- 审计或现代化一个目录、PR 或整个代码仓库(所需流程见
references/_review-algorithm.md) - 从 React 18 迁移到 React 19(forwardRef → ref 作为属性,
<Context.Provider>→<Context>,useFormState→useActionState) - 优化重新渲染性能或包体积
- 使用并发特性(useTransition、useDeferredValue、Activity)
- 设置服务端组件或服务端/客户端边界
- 实现表单 Action、乐观更新或数据获取
- 配置 React Compiler 以实现自动记忆化
- 检查 React 代码中的常见反模式或过时的 React 18 习惯用法
- 查找单文件规则无法发现的代码库级问题:跨文件重复逻辑、近似重复的组件、死代码、不需要客户端的
'use client'文件、属性形状漂移(见类别 9)
如何检查或重构代码库
当用户要求检查、重构、现代化或审计 React 代码(单个文件或整个代码仓库)时,请遵循 references/_review-algorithm.md。不要自行发挥。
该文档规定的四项不可妥协要求:
- 两种模式——绝不拒绝对整个代码仓库进行审计。 选择 模式 A(范围有限,≤约 20 个文件)或 模式 B(整个目录树:清点 + 定向扫描 + 完整类别 9)。算法会告诉你如何处理“审计我的代码库”这类请求,而不必将 800 个文件全部塞进上下文。
- 依靠判断,而非 grep。 每条规则定义的是一种模式形态,而非语法标记。开始扫描前,先阅读每条规则中的需要识别的形态一节——grep 能找到容易发现的违规,却会漏掉高价值问题(作者为绕开
forwardRef而手动层层传递的回调 ref;用onSubmit完成了本该由useActionState处理的工作;形似派生状态的useState+useEffect;隐藏了获取数据流程的自定义 Hook)。grep 是触发器,绝不是判定依据。 - 按类别扫描,而非按文件扫描——并设置强制检查机制。 按优先级(CRITICAL → … → CROSS-CUTTING)一次扫描一个类别,并覆盖范围内的所有文件。算法要求提供范围声明、各类别进度行,以及最终的覆盖表(
category × file,单元格 ∈{clean, N findings, n/a})。输出中缺少某个类别会立即显现。 - 代码库级问题由类别 9 发现。 单文件规则无法判断“这两个组件应当合并”或“这个 Hook 已经没有用途”。类别 9(代码卫生)会在最后扫描完整文件清单,并提出删除、去重、复用或合并方面的发现。
单文件的临时问题(“这个 Hook 可以吗?”)可以直接查看相关规则。该算法适用于多文件和整个代码仓库的情况。
规则类别
| # | 类别 | 影响 | 规则 | 关键主题 |
|---|---|---|---|---|
| 1 | 并发渲染 | CRITICAL | 6 | useTransition、useDeferredValue、Activity、批处理、渲染纯度 |
| 2 | 服务端组件 | CRITICAL | 6 | RSC 边界、数据获取、流式传输、可序列化的属性 |
| 3 | Actions 与表单 | HIGH | 5 | 表单 actions、声明式表单状态、useOptimistic、服务端验证 |
| 4 | 数据获取 | HIGH | 7 | use() hook、cache()、Suspense、文档元数据、资源提示 |
| 5 | 状态管理 | MEDIUM-HIGH | 5 | 派生值、上下文拆分、函数式更新、reducer |
| 6 | 记忆化与性能 | MEDIUM | 5 | React Compiler、useMemo、useCallback、React.memo |
| 7 | Effects 与事件 | MEDIUM | 5 | useEffectEvent、清理、外部存储、派生状态反模式 |
| 8 | 组件模式 | LOW-MEDIUM | 5 | 将 ref 作为属性、组合、受控与非受控、key 重置 |
| 9 | 代码库整洁 | CROSS-CUTTING | 5 | 去重、整合、死代码、边界一致性、属性形态漂移 |
快速参考
关键模式——优先掌握这些:
- 在服务端组件中获取数据,而非客户端组件
- 尽可能将
'use client'边界下移 - 对开销较大的非阻塞更新使用
startTransition - 使用
<Activity>在切换标签页或页面时保留状态
React 19 现代惯用写法(不要生成 React 18 模式):
function C({ ref, ...props })— 不要使用forwardRef包装<MyContext value={v}>— 不要使用<MyContext.Provider>useActionState— 不要使用useFormStateuseRef<T>(null)— 始终传入初始值- 内联渲染
<title>、<meta>、<link>— 不要使用react-helmet - 使用来自
react-dom的preload/preconnect— 不要手动渲染<link rel="preload">
常见的单文件错误——避免这些反模式:
- 在客户端组件中为
use()创建 promise(会导致无限循环) - 记忆化所有内容(改用 React Compiler v1.0+)
- 使用 effects 处理派生状态、变更、通知父组件或应用初始化
- 在组件树中过早放置
'use client'
代码库层面的模式——在第 9 类检查中发现这些问题:
- 没有任何导入方的组件、hooks 或工具函数——删除
- 2 个或更多文件具有相同的 effect/状态形态——提取为共享 hook
- 2 个或更多结构相同、但标签或图标存在差异的组件——使用变体或组合进行整合
- hook 用法无需客户端执行的
'use client'文件——降级为服务端组件(或拆分为服务端父组件 + 客户端岛) - 不同组件中用不同名称表示的同一概念属性——统一为规范名称
目录
- 并发渲染 — CRITICAL
- 1.1 导航时保留隐藏子树状态,而不是卸载 — HIGH(
<Activity>) - 1.2 将更新包在 transition 中,使导航时旧内容继续显示 — HIGH
- 1.3 信任自动批处理——不要轻易使用 flushSync 或 unstable_batchedUpdates — HIGH
- 1.4 当某个值驱动开销较大的子组件重新渲染时,延迟处理你不拥有的值 — CRITICAL(
useDeferredValue) - 1.5 将开销较大的状态更新标记为低优先级,确保输入保持响应 — CRITICAL(
useTransition) - 1.6 保持渲染纯粹——渲染期间绝不修改、订阅或读取外部状态 — MEDIUM-HIGH
- 1.1 导航时保留隐藏子树状态,而不是卸载 — HIGH(
- 服务端组件 — CRITICAL
- 2.1 将依赖浏览器 API 的库隔离在客户端组件包装器中 — MEDIUM-HIGH
- 2.2 将缓慢的异步工作置于独立的 Suspense 边界之后,让快速内容先流式传输 — MEDIUM-HIGH
- 2.3 在服务端使用 async/await 获取数据——绝不要在客户端组件中使用
useEffect+fetch— CRITICAL - 2.4 将
'use client'边界下推到交互式叶子组件,而不是上移到路由层 — CRITICAL - 2.5 只有 RSC 线格式可编码的数据才能跨越服务端→客户端边界 — HIGH
- 2.6 服务端内容通过
children或具名插槽进入客户端组件,而不是通过导入 — HIGH
- Actions 与表单 — HIGH
- 3.1 通过
action属性处理表单提交,而不是仅使用 JS 的onSubmit处理器 — HIGH - 3.2 用单个声明式表单状态 Hook 统一管理命令式的待处理、错误和提交状态 — HIGH(
useActionState) - 3.3 提交按钮通过上下文读取父表单的待处理状态,而不是通过 prop 层层传递 — MEDIUM-HIGH(
useFormStatus) - 3.4 立即显示变更后的结果,并在失败时自动回滚 — HIGH(
useOptimistic) - 3.5 将验证视为服务端 Action 的职责;客户端检查只是增强,绝不能是唯一关卡 — MEDIUM
- 3.1 通过
- 数据获取 — HIGH
- 4.1 独立的获取操作应并发执行——顺序
await会造成瀑布流 — MEDIUM-HIGH - 4.2 按请求记忆化数据获取器,避免多个组件读取相同数据时重复获取 — HIGH(
cache()) - 4.3 每个 Suspense 边界都需要由 Error Boundary 包裹——必须能够隔离故障 — MEDIUM
- 4.4 使用 Suspense 回退声明加载状态,而不是通过
if (loading) return …拼装 — HIGH - 4.5 使用
use()读取 Promise 和条件上下文,而不是用useEffect+useState处理 — HIGH(use()) - 4.6 页面元数据直接以内联的
<title>/<meta>/<link>渲染——弃用 helmet 风格的 head 管理器 — MEDIUM - 4.7 使用
react-dom的命令式资源提示 API,而不是手动渲染<link rel="preload">— MEDIUM
- 4.1 独立的获取操作应并发执行——顺序
- 状态管理 — MEDIUM-HIGH
- 5.1 在渲染函数体中计算派生值——绝不要将它们镜像到独立状态中 — MEDIUM
- 5.2 每个上下文只保存一个独立变化的状态——将臃肿的上下文拆分开 — MEDIUM
- 5.3 当下一个状态取决于前一个状态时,传入
setX(prev => …),而不是setX(x + 1)— MEDIUM-HIGH - 5.4 当初始值计算开销较大时,向
useState传入函数——绝不要直接内联计算 — MEDIUM-HIGH - 5.5 需要协调多个字段的状态转换时,使用单个 reducer,而不是 N 个并列的
useState单元 — MEDIUM(useReducer)
- 记忆化与性能 — MEDIUM
- 6.1 根据测量所得的基线进行记忆化——不要预先用 useMemo/useCallback 包装每个值和回调 — MEDIUM
- 6.2 采用 React Compiler v1.0——让构建过程负责记忆化,然后移除手动添加的
useMemo/useCallback冗余代码 — MEDIUM - 6.3 仅当昂贵的纯组件的 props 确实稳定时,才用
memo()包装 — MEDIUM - 6.4 仅当下游逻辑依赖回调标识稳定性时,才稳定回调的标识 — MEDIUM(
useCallback) - 6.5 仅当输入稳定且计算开销经测量确实较大时,才在渲染间缓存计算结果 — MEDIUM(
useMemo)
- Effects 与事件 — MEDIUM
- 7.1 每个执行订阅、调度或连接的 effect 都必须返回清理函数来拆除这些操作 — MEDIUM
- 7.2
useEffect用于与外部系统同步——绝不用它处理派生状态、变更、事件逻辑、通知父组件或应用初始化 — HIGH - 7.3 Effect 依赖项按引用比较——传入基本类型,而不是在渲染中创建的对象或数组 — MEDIUM
- 7.4 在 effect 回调中读取最新的 props/state,且这些值变化时无需重新订阅 — MEDIUM(
useEffectEvent) - 7.5 通过
useSyncExternalStore订阅外部可变状态,而不是使用useEffect+useState— MEDIUM
- 组件模式 — LOW-MEDIUM
- 8.1 组件将
ref作为普通解构 prop 接收——移除forwardRef包装器,停止逐层传递 — MEDIUM-HIGH - 8.2 仅当有其他内容需要在每次变化时读取该值,才使用受控状态;否则优先使用带
<form action>的非受控方式 — LOW-MEDIUM - 8.3 当 prop 数量超过约 6 个且包含许多可选插槽时,改用
children并让调用方组合 — LOW-MEDIUM - 8.4 设置
key={entity.id},将有状态子组件的标识与其编辑的实体绑定——让 React 为你清除过时状态 — LOW-MEDIUM - 8.5 仅当父组件需要控制渲染时才使用渲染 prop;复用逻辑时优先使用自定义 Hook — LOW-MEDIUM
- 8.1 组件将
- 代码库整洁度 — CROSS-CUTTING(涉及多个文件的发现;整仓库审计必需)
- 9.1 将重复的 effect/state 结构提取为共享 Hook — HIGH
- 9.2 将近似重复的组件合并为一个组件,通过变体或组合实现差异 — HIGH
- 9.3 删除没有任何导入者的组件、Hook 和工具函数 — MEDIUM-HIGH
- 9.4 对于 Hook 用法不需要客户端环境的文件,移除其 'use client' 声明 — HIGH
- 9.5 同一概念在不同组件中使用不同 prop 名称时,统一采用规范名称 — MEDIUM-HIGH
参考资料
- https://react.dev
- https://react.dev/blog/2024/04/25/react-19-upgrade-guide
- https://react.dev/blog/2024/12/05/react-19
- https://react.dev/blog/2025/10/01/react-19-2
- https://react.dev/blog/2025/10/07/react-compiler-1
- https://react.dev/learn/you-might-not-need-an-effect
- https://github.com/facebook/react
相关技能
- 关于 Next.js 16 App Router,请参阅
nextjs-16-app-router技能 - 关于客户端表单处理,请参阅
react-hook-form技能 - 关于使用 TanStack Query 缓存数据,请参阅
tanstack-query技能