SKILL.md
readonly只读
name
react-patterns
description
提供全面的 React 19 模式,涵盖服务端组件、服务端操作、useOptimistic、useActionState、useTransition、并发特性、Suspense 边界以及 TypeScript 集成。生成可执行的代码模式,验证公共端点的安全性,并通过 React Compiler 或手动记忆化优化性能。在构建使用 Next.js App Router 的 React 19 应用程序、实现乐观 UI 或优化并发渲染时主动使用。
React 19 开发模式
概述
适用于 Next.js App Router、服务端操作、乐观 UI 和并发特性的 React 19 模式。参见快速参考了解 API 摘要,以及示例获取可复制粘贴的模式。
使用时机
- 使用 Next.js App Router 构建 React 19 应用程序
- 使用
useOptimistic或useTransition实现乐观 UI - 创建带表单验证的服务端操作
- 从类组件迁移到 Hooks
- 使用 React Compiler 优化并发渲染
- 使用
useReducer或自定义 Hooks 管理复杂状态 - 将异步操作包裹在 Suspense 边界中
快速参考
| 模式 | Hook / API | 使用场景 |
|---|---|---|
| 本地状态 | useState |
简单的组件状态 |
| 复杂状态 | useReducer |
多操作状态机 |
| 副作用 | useEffect |
订阅、数据获取 |
| 共享状态 | useContext / createContext |
跨组件数据 |
| DOM 访问 | useRef |
焦点、测量、定时器 |
| 性能优化 | useMemo / useCallback |
昂贵计算 |
| 非紧急更新 | useTransition |
大型列表的搜索/过滤 |
| 延迟昂贵 UI | useDeferredValue |
陈旧时更新 |
| 读取资源 | use() (React 19) |
在渲染中处理 Promise 和上下文 |
| 乐观 UI | useOptimistic (React 19) |
突变操作的即时反馈 |
| 表单状态 | useFormStatus (React 19) |
子组件中的待处理状态 |
| 表单状态管理 | useActionState (React 19) |
服务端操作结果 |
| 自动记忆化 | React Compiler | 消除手动 memo/callback |
操作指南
- 识别组件类型:确定需要服务端组件还是客户端组件
- 选择 Hooks:使用适当的 Hooks 进行状态管理和副作用处理
- 类型化 Props:为所有组件 props 定义 TypeScript 接口
- 处理异步:将数据获取组件包裹在 Suspense 边界中
- 优化:使用 React Compiler 或手动记忆化处理昂贵渲染
- 处理错误:添加 ErrorBoundary 实现优雅的错误处理
- 验证服务端操作:定义 Zod/schema 验证,然后测试:
- 提交无效输入 → 验证拒绝
- 提交有效输入 → 验证成功
示例
服务端组件与客户端交互
// 服务端组件(默认)— 异步,获取数据
async function ProductPage({ id }: { id: string }) {
const product = await db.product.findUnique({ where: { id } });
return (
<div>
<h1>{product.name}</h1>
<AddToCartButton productId={product.id} />
</div>
);
}
// 客户端组件 — 处理交互
'use client';
function AddToCartButton({ productId }: { productId: string }) {
const [isPending, startTransition] = useTransition();
const handleAdd = () => {
startTransition(async () => {
await addToCart(productId);
});
};
return (
<button onClick={handleAdd} disabled={isPending}>
{isPending ? '添加中...' : '加入购物车'}
</button>
);
}
useOptimistic 实现即时反馈
'use client';
import { useOptimistic } from 'react';
function TodoList({ todos, addTodo }: { todos: Todo[]; addTodo: (t: Todo) => Promise<void> }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo: Todo) => [...state, { ...newTodo, pending: true }]
);
const handleSubmit = async (formData: FormData) => {
const newTodo = { id: Date.now(), text: formData.get('text') as string };
addOptimisticTodo(newTodo); // 立即更新 UI
await addTodo(newTodo); // 实际后端调用
};
return (
<form action={handleSubmit}>
{optimisticTodos.map(todo => (
<div key={todo.id} style={{ opacity: todo.pending ? 0.5 : 1 }}>
{todo.text}
</div>
))}
<input type="text" name="text" />
<button type="submit">添加</button>
</form>
);
}
带表单的服务端操作
// app/actions.ts
'use server';
import { z } from 'zod';
import { revalidatePath } from 'next/cache';
const schema = z.object({
title: z.string().min(5),
content: z.string().min(10),
});
export async function createPost(prevState: any, formData: FormData) {
const parsed = schema.safeParse({
title: formData.get('title'),
content: formData.get('content'),
});
if (!parsed.success) {
return { errors: parsed.error.flatten().fieldErrors };
}
await db.post.create({ data: parsed.data });
revalidatePath('/posts');
return { success: true };
}
// app/blog/new/page.tsx
'use client';
import { useActionState } from 'react';
import { createPost } from '../actions';
export default function NewPostPage() {
const [state, formAction, pending] = useActionState(createPost, {});
return (
<form action={formAction}>
<input name="title" placeholder="标题" />
{state.errors?.title && <span>{state.errors.title[0]}</span>}
<textarea name="content" placeholder="内容" />
<button type="submit" disabled={pending}>
{pending ? '发布中...' : '发布'}
</button>
</form>
);
}
自定义 Hook
export function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
function handleOnline() { setIsOnline(true); }
function handleOffline() { setIsOnline(false); }
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
return isOnline;
}
useTransition 处理非紧急更新
function SearchableList({ items }: { items: Item[] }) {
const [query, setQuery] = useState('');
const [isPending, startTransition] = useTransition();
const [filteredItems, setFilteredItems] = useState(items);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setQuery(e.target.value);
startTransition(() => {
setFilteredItems(items.filter(i => i.name.toLowerCase().includes(e.target.value.toLowerCase())));
});
};
return (
<div>
<input value={query} onChange={handleChange} />
{isPending && <span>过滤中...</span>}
<ul>{filteredItems.map(i => <li key={i.id}>{i.name}</li>)}</ul>
</div>
);
}
最佳实践
服务端与客户端决策
- 从服务端组件开始(无需指令)
- 仅在需要 Hooks、浏览器 API 或事件处理程序时添加
'use client'
状态管理
- 保持状态最小化 — 在渲染期间计算派生值,而非在 effect 中
- 对于具有多个相关操作的状态,使用
useReducer - 将状态提升到最近的共同祖先
Effects
- 仅将 effects 用于外部系统同步
- 始终指定正确的依赖数组
- 为订阅和定时器返回清理函数
- 永远不要直接修改状态 — 始终创建新引用
性能
- 使用 React Compiler 时:避免手动使用
useMemo、useCallback、memo - 未使用 React Compiler 时:对昂贵计算使用
useMemo,对稳定回调使用useCallback - 对低优先级状态更新使用
useTransition - 使用稳定 ID 作为列表键,而非数组索引
React 19 特定
- 将
use(promise)组件包裹在 Suspense 边界中 - 使用
useActionState实现表单与服务端操作的集成 - 验证服务端操作输入 — 它们是公共端点
- 从服务端组件向客户端组件传递可序列化数据
约束与警告
- 服务端组件:不能使用 Hooks、事件处理程序或浏览器 API
- use() Hook:只能在渲染期间调用,不能在回调或 effects 中调用
- 服务端操作:必须包含
'use server'指令;始终验证输入 - 状态修改:永远不要直接修改状态 — 始终创建新引用
- Effect 依赖:在
useEffect依赖数组中包含所有依赖 - 内存泄漏:始终在 useEffect 返回中清理订阅和事件监听器
参考资料
查阅以下文件获取详细模式:
- references/hooks-patterns.md — useState、useEffect、useRef、useReducer、自定义 Hooks、常见陷阱
- references/component-patterns.md — Props、组合、状态提升、上下文、复合组件、错误边界
- references/react19-features.md — use()、useOptimistic、useFormStatus、useActionState、服务端操作、服务端组件、迁移指南
- references/performance-patterns.md — React Compiler 设置、useMemo、useCallback、useTransition、useDeferredValue、懒加载
- references/typescript-patterns.md — 类型化 Props、泛型组件、事件处理程序、可辨识联合、上下文类型化
- references/learn.md — 从基础到高级 React 19 的渐进学习指南
- references/reference.md — 所有 React Hooks 和组件 API 的完整 API 参考






