关于 react-19
面向 React 19 开发者的参考技能,介绍新钩子和表单 Actions,以及 Server Components、Server Actions 和 React Compiler,并提供迁移与故障排查指导。
主要功能
- 01使用 Actions 执行异步变更
- 02通过 useActionState 和 useFormStatus 管理表单
- 03使用 useOptimistic 实现乐观界面更新
- 04使用 Server Components 和 Server Actions
- 05了解 React Compiler 与 ref 属性
适用场景
- 01构建带待处理和错误状态的表单
- 02在数据更新期间提供即时反馈
- 03使用服务器渲染组件组织应用
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill react-19安装后在 Claude Code 中输入/react-19确认已加载。
附带文件hooks.mdserver.md
详细介绍
React 19
新功能概览
| 功能 | 描述 |
|---|---|
| Actions | 在 transition 中使用异步函数处理数据变更 |
useActionState | 管理操作状态,包括待处理和错误状态 |
useFormStatus | 访问父级表单状态 |
useOptimistic | 乐观 UI 更新 |
use() | 在渲染期间读取资源(Promises、Context) |
| Server Components | 在服务端渲染的组件 |
| Server Actions | 由客户端调用的服务端函数 |
| React Compiler | 自动记忆化 |
| Ref 作为 prop | 无需使用 forwardRef,直接传递 ref |
Actions
Actions 是在 transition 中用于处理变更的异步函数:
import { useTransition } from 'react';
function UpdateProfile() {
const [isPending, startTransition] = useTransition();
async function handleSubmit(formData: FormData) {
startTransition(async () => {
const result = await updateProfile(formData);
if (result.error) {
showToast(result.error);
}
});
}
return (
<form action={handleSubmit}>
<input name="name" type="text" />
<button type="submit" disabled={isPending}>
{isPending ? 'Saving...' : 'Save'}
</button>
</form>
);
}
useActionState
替代实验性的 useFormState。管理表单操作状态,包括待处理状态:
import { useActionState } from 'react';
interface FormState {
message: string | null;
errors: Record<string, string[]>;
}
async function createPost(prevState: FormState, formData: FormData): Promise<FormState> {
const title = formData.get('title') as string;
if (!title || title.length < 3) {
return { message: null, errors: { title: ['Title must be at least 3 characters'] } };
}
try {
await savePost({ title });
return { message: 'Post created!', errors: {} };
} catch (error) {
return { message: 'Failed to create post', errors: {} };
}
}
function CreatePostForm() {
const [state, formAction, isPending] = useActionState(createPost, {
message: null,
errors: {}
});
return (
<form action={formAction}>
<input name="title" type="text" />
{state.errors.title && <p className="error">{state.errors.title[0]}</p>}
<button type="submit" disabled={isPending}>
{isPending ? 'Creating...' : 'Create Post'}
</button>
</form>
);
}
useFormStatus
从任意子组件访问父级 <form> 的状态:
import { useFormStatus } from 'react-dom';
function SubmitButton() {
const { pending, data, method, action } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? 'Submitting...' : 'Submit'}
</button>
);
}
// Usage - must be child of <form>
function ContactForm() {
return (
<form action={submitContact}>
<input name="email" type="email" required />
<SubmitButton />
</form>
);
}
可复用表单组件
'use client';
import { useFormStatus } from 'react-dom';
export function FormButton({ children, pendingText = 'Submitting...', ...props }) {
const { pending } = useFormStatus();
return (
<button {...props} disabled={pending || props.disabled}>
{pending ? pendingText : children}
</button>
);
}
完整参考:请参阅 hooks.md,了解 useOptimistic、use() Hook、Ref 处理和文档元数据。
Server Components 与 Server Actions
// app/users/page.tsx (Server Component by default)
export default async function UsersPage() {
const users = await fetchUsers();
return <UserList users={users} />;
}
// app/actions.ts
'use server';
export async function createPost(formData: FormData) {
const title = formData.get('title') as string;
await db.post.create({ data: { title } });
revalidatePath('/posts');
redirect(`/posts`);
}
完整参考:请参阅 server.md,了解 Server Components 模式、React Compiler 和迁移指南。
最佳实践
- ✅ 使用 Actions 处理表单提交和数据变更
- ✅ 使用
useOptimistic提供即时反馈 - ✅ 使用
use()代替 useEffect 获取数据 - ✅ 让 React Compiler 处理记忆化
- ✅ 使用 Server Components 呈现静态内容
- ✅ 使用 Server Actions 安全地处理数据变更
- ❌ 不要在组件内为
use()创建 Promises - ❌ 不要在缺少适当边界的情况下混用客户端和服务端代码
不适合使用此技能的情况
- React 18 及更早版本的功能——请改用
react技能 - 通用表单处理——请使用
react-forms或react-hook-form技能 - 性能优化——请使用
react-performance技能
反模式
| 反模式 | 问题 | 解决方案 |
|---|---|---|
| 在渲染期间为 use() 创建 Promises | 每次渲染都会创建新的 Promise | 在组件外创建 Promise |
| 使用 useFormState 而非 useActionState | 在 React 19 中已弃用 | 使用带有 isPending 的 useActionState |
| 缺少 'use server' 指令 | 代码会在客户端运行 | 在文件顶部添加 'use server' |
| 不验证 Server Action 的输入 | 安全漏洞 | 始终使用 Zod 验证 |
快速故障排除
| 问题 | 可能原因 | 修复方法 |
|---|---|---|
| Action 不起作用 | 缺少 action 属性 | 在表单中添加 action={serverAction} |
| isPending 不可用 | 正在使用旧版 useFormState | 改用 useActionState |
| 序列化错误 | 传递了函数或类 | 仅传递可序列化的数据 |
| ref 不起作用 | 使用了旧版 forwardRef 模式 | 将 ref 作为常规 prop 传递 |
参考文件
| 文件 | 内容 |
|---|---|
| hooks.md | useOptimistic、use()、Ref 处理、元数据 |
| server.md | Server Components、Server Actions、Compiler、迁移 |
外部文档
评论
支持 Markdown