react-19

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

React 19

React 19

Overview of New Features

新特性概述

FeatureDescription
ActionsAsync functions in transitions for data mutations
useActionState
Handle action state with pending/error
useFormStatus
Access parent form status
useOptimistic
Optimistic UI updates
use()
Read resources in render (Promises, Context)
Server ComponentsComponents that render on server
Server ActionsServer functions called from client
React CompilerAutomatic memoization
Ref as propPass ref directly without forwardRef

特性描述
Actions用于数据变更的过渡态异步函数
useActionState
处理包含等待/错误状态的动作状态
useFormStatus
访问父表单状态
useOptimistic
乐观UI更新
use()
在渲染中读取资源(Promises、Context)
Server Components在服务器端渲染的组件
Server Actions从客户端调用的服务器端函数
React Compiler自动记忆化处理
Ref as prop直接传递ref,无需forwardRef

Actions

Actions

Actions are async functions used in transitions to handle mutations:
tsx
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>
  );
}

Actions是用于过渡态中处理数据变更的异步函数:
tsx
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 ? '保存中...' : '保存'}
      </button>
    </form>
  );
}

useActionState

useActionState

Replaces the experimental
useFormState
. Manages form action state including pending status:
tsx
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>
  );
}

替代实验性的
useFormState
,管理包含等待状态的表单动作状态:
tsx
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: ['标题长度至少为3个字符'] } };
  }

  try {
    await savePost({ title });
    return { message: '帖子创建成功!', errors: {} };
  } catch (error) {
    return { message: '帖子创建失败', 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 ? '创建中...' : '创建帖子'}
      </button>
    </form>
  );
}

useFormStatus

useFormStatus

Access the status of a parent
<form>
from any child component:
tsx
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>
  );
}
从任意子组件访问父
<form>
的状态:
tsx
import { useFormStatus } from 'react-dom';

function SubmitButton() {
  const { pending, data, method, action } = useFormStatus();

  return (
    <button type="submit" disabled={pending}>
      {pending ? '提交中...' : '提交'}
    </button>
  );
}

// 使用方式 - 必须是<form>的子组件
function ContactForm() {
  return (
    <form action={submitContact}>
      <input name="email" type="email" required />
      <SubmitButton />
    </form>
  );
}

Reusable Form Components

可复用表单组件

tsx
'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>
  );
}
Full Reference: See hooks.md for useOptimistic, use() hook, Ref handling, Document Metadata.

tsx
'use client';
import { useFormStatus } from 'react-dom';

export function FormButton({ children, pendingText = '提交中...', ...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

Server Components & Server Actions

tsx
// 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`);
}
Full Reference: See server.md for Server Components patterns, React Compiler, Migration Guide.

tsx
// app/users/page.tsx(默认是Server Component)
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、迁移指南的相关内容。

Best Practices

最佳实践

  • ✅ Use Actions for form submissions and mutations
  • ✅ Use
    useOptimistic
    for immediate feedback
  • ✅ Use
    use()
    instead of useEffect for data fetching
  • ✅ Let React Compiler handle memoization
  • ✅ Use Server Components for static content
  • ✅ Use Server Actions for secure mutations
  • ❌ Don't create Promises inside components for
    use()
  • ❌ Don't mix client/server code without proper boundaries

  • ✅ 使用Actions处理表单提交和数据变更
  • ✅ 使用
    useOptimistic
    实现即时反馈
  • ✅ 使用
    use()
    替代useEffect进行数据获取
  • ✅ 让React Compiler处理记忆化
  • ✅ 使用Server Components处理静态内容
  • ✅ 使用Server Actions处理安全的变更操作
  • ❌ 不要在组件内部为
    use()
    创建Promises
  • ❌ 不要在未设置正确边界的情况下混合客户端/服务器端代码

When NOT to Use This Skill

不适用本技能的场景

  • React 18 and earlier features - Use
    react
    skill instead
  • General form handling - Use
    react-forms
    or
    react-hook-form
    skills
  • Performance optimization - Use
    react-performance
    skill

  • React 18及更早版本特性 - 请使用
    react
    技能
  • 通用表单处理 - 请使用
    react-forms
    react-hook-form
    技能
  • 性能优化 - 请使用
    react-performance
    技能

Anti-Patterns

反模式

Anti-PatternProblemSolution
Creating Promises in render for use()New promise every renderCreate promise outside component
Using useFormState instead of useActionStateDeprecated in React 19Use useActionState with isPending
Missing 'use server' directiveCode runs on clientAdd 'use server' at top of file
Not validating Server Action inputsSecurity vulnerabilityAlways validate with Zod

反模式问题解决方案
在渲染中为use()创建Promises每次渲染都会生成新的Promise在组件外部创建Promise
使用useFormState而非useActionStateReact 19中已废弃使用带isPending的useActionState
缺少'use server'指令代码在客户端运行在文件顶部添加'use server'
未验证Server Action输入安全漏洞始终使用Zod进行验证

Quick Troubleshooting

快速故障排除

IssueLikely CauseFix
Action not workingMissing action attributeAdd action={serverAction} to form
isPending not availableUsing old useFormStateSwitch to useActionState
Serialization errorsPassing functions/classesOnly pass serializable data
ref not workingUsing old forwardRef patternPass ref as regular prop

问题可能原因修复方案
Action无法工作缺少action属性为form添加action={serverAction}
isPending不可用使用了旧版useFormState切换为useActionState
序列化错误传递了函数/类仅传递可序列化的数据
ref无法工作使用了旧版forwardRef模式将ref作为常规属性传递

Reference Files

参考文件

FileContent
hooks.mduseOptimistic, use(), Ref handling, Metadata
server.mdServer Components, Server Actions, Compiler, Migration

文件内容
hooks.mduseOptimistic、use()、Ref处理、元数据
server.mdServer Components模式、React Compiler、迁移指南

External Documentation

外部文档