react-19 について
React 19 を使う開発者向けのリファレンススキルです。新しいフックやフォーム Actions に加え、Server Components、Server Actions、React Compiler を解説し、移行とトラブルシューティングも扱います。
主な機能
- 01Actions による非同期ミューテーション
- 02useActionState と useFormStatus によるフォーム管理
- 03useOptimistic による楽観的 UI 更新
- 04Server Components と Server Actions の利用
- 05React 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 | データの変更を行うための、トランジション内での非同期関数 |
useActionState | 保留中/エラーを含むアクションの状態を管理 |
useFormStatus | 親フォームの状態にアクセス |
useOptimistic | 楽観的 UI 更新 |
use() | レンダリング中にリソース(Promises、Context)を読み取る |
| Server Components | サーバー上でレンダリングされるコンポーネント |
| Server Actions | クライアントから呼び出されるサーバー関数 |
| React Compiler | 自動メモ化 |
| Ref as prop | forwardRef を使わずに ref を直接渡す |
Actions
Actions は、変更を処理するためにトランジション内で使用される非同期関数です。
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>
);
}
詳しいリファレンス:useOptimistic、use() フック、Ref の処理、ドキュメントメタデータについては、hooks.md を参照してください。
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 Components のパターン、React Compiler、移行ガイドについては、server.md を参照してください。
ベストプラクティス
- ✅ フォーム送信と変更には Actions を使用します
- ✅ すぐにフィードバックを返すには
useOptimisticを使用します - ✅ データ取得には useEffect の代わりに
use()を使用します - ✅ メモ化は React Compiler に任せます
- ✅ 静的コンテンツには Server Components を使用します
- ✅ 安全な変更には Server Actions を使用します
- ❌
use()のためにコンポーネント内で Promises を作成しないでください - ❌ 適切な境界を設けずにクライアントコードとサーバーコードを混在させないでください
このスキルを使用しない場合
- React 18 以前の機能 -
reactスキルを使用してください - 一般的なフォーム処理 -
react-formsまたはreact-hook-formスキルを使用してください - パフォーマンス最適化 -
react-performanceスキルを使用してください
アンチパターン
| アンチパターン | 問題 | 解決策 |
|---|---|---|
| use() 用の Promises をレンダリング中に作成する | レンダリングのたびに新しい Promise が作成される | コンポーネントの外で Promise を作成する |
| useActionState の代わりに useFormState を使用する | React 19 では非推奨 | isPending とともに useActionState を使用する |
| 'use server' ディレクティブがない | コードがクライアント上で実行される | ファイルの先頭に 'use server' を追加する |
| Server Action の入力を検証しない | セキュリティ上の脆弱性 | 常に Zod で検証する |
簡単なトラブルシューティング
| 問題 | 考えられる原因 | 対処法 |
|---|---|---|
| Action が動作しない | action 属性がない | フォームに action={serverAction} を追加する |
| isPending を使用できない | 古い useFormState を使用している | useActionState に切り替える |
| シリアル化エラー | 関数やクラスを渡している | シリアル化可能なデータのみを渡す |
| ref が動作しない | 古い forwardRef パターンを使用している | 通常の prop として ref を渡す |
リファレンスファイル
| ファイル | 内容 |
|---|---|
| hooks.md | useOptimistic、use()、Ref の処理、メタデータ |
| server.md | Server Components、Server Actions、Compiler、移行 |
外部ドキュメント
コメント
Markdown 対応