React 19 新機能完全ガイド:Actions、use()、Server Components、コンパイラ最適化
前端工程(更新: 2026年5月6日)
React 19:フレームワークレベルのパラダイムアップグレード
React 19 は単なる API 更新ではなく、「ライブラリ」から「フルスタックフレームワーク」への位置づけの転換です。Server Components、Actions、Compiler の 3 大機能が React アプリケーションの書き方を再定義します。
| 機能 | 解決する問題 | 影響範囲 |
|---|---|---|
| Form Actions | フォーム送信のボイラープレートコード | すべてのフォーム操作 |
| use() フック | 条件付きデータ読み込み | データ取得パターン |
| Server Components | クライアントバンドルサイズ | アーキテクチャ全体 |
| React Compiler | 手動 memo 最適化 | パフォーマンス |
| ref as prop | forwardRef ボイラープレート | コンポーネント API |
| Document Metadata | SEO/head 管理 | SSR アプリケーション |
1. Form Actions:フォームボイラープレートにさようなら
従来の書き方
function LoginForm() {
const [pending, setPending] = useState(false);
const [error, setError] = useState(null);
async function handleSubmit(e) {
e.preventDefault();
setPending(true);
setError(null);
try {
const formData = new FormData(e.target);
await login(formData.get('email'), formData.get('password'));
} catch (err) {
setError(err.message);
} finally {
setPending(false);
}
}
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" />
<input name="password" type="password" />
<button disabled={pending}>{pending ? 'ログイン中...' : 'ログイン'}</button>
{error && <p>{error}</p>}
</form>
);
}
React 19 の書き方
async function loginAction(formData) {
// サーバー上で直接実行、手動の pending/error 管理不要
await login(formData.get('email'), formData.get('password'));
}
function LoginForm() {
return (
<form action={loginAction}>
<input name="email" type="email" />
<input name="password" type="password" />
<SubmitButton />
</form>
);
}
// useActionStatus が送信状態を自動追跡
function SubmitButton() {
const { pending } = useActionStatus();
return <button disabled={pending}>{pending ? 'ログイン中...' : 'ログイン'}</button>;
}
コード削減:約 60%。onSubmit、preventDefault、手動の pending/error 状態が不要に。
useActionState:フォーム状態の管理
function LoginForm() {
const [state, formAction, isPending] = useActionState(
async (prevState, formData) => {
try {
await login(formData.get('email'), formData.get('password'));
return { success: true };
} catch (err) {
return { error: err.message };
}
},
null
);
return (
<form action={formAction}>
<input name="email" type="email" />
<input name="password" type="password" />
<button disabled={isPending}>ログイン</button>
{state?.error && <p className="error">{state.error}</p>}
</form>
);
}
2. use() フック:条件付きデータ読み込み
use() は React 初の条件文やループ内で呼び出せるフックです。
Promise の読み取り
function UserProfile({ userPromise }) {
// 条件文内で使用可能!
if (showProfile) {
const user = use(userPromise);
return <h1>{user.name}</h1>;
}
return null;
}
Context の読み取り
function ThemeToggle() {
// 以前は useContext が必要、今は use() を使用可能
const theme = use(ThemeContext);
return <button onClick={toggle}>{theme}</button>;
}
Suspense 統合
function UserPage({ userPromise }) {
return (
<Suspense fallback={<Spinner />}>
<UserProfile userPromise={userPromise} />
</Suspense>
);
}
function UserProfile({ userPromise }) {
const user = use(userPromise);
return <div>{user.name}</div>;
}
3. Server Components 正式安定版
Server と Client コンポーネント
// Server Component(デフォルト)
// - サーバーでレンダリング、JS をクライアントに送信しない
// - データベース、ファイルシステムに直接アクセス可能
// - useState、useEffect、イベントハンドラは使用不可
async function BlogList() {
const posts = await db.query('SELECT * FROM posts');
return (
<ul>
{posts.map(post => (
<li key={post.id}>
<h2>{post.title}</h2>
<LikeButton postId={post.id} /> {/* Client Component */}
</li>
))}
</ul>
);
}
// Client Component
'use client';
// - クライアントでレンダリング(SSR も可能)
// - すべてのフックを使用可能
// - バンドルされてクライアントに送信
function LikeButton({ postId }) {
const [liked, setLiked] = useState(false);
return <button onClick={() => setLiked(!liked)}>❤️</button>;
}
Server Actions
'use server';
async function createPost(formData) {
const title = formData.get('title');
const content = formData.get('content');
await db.insert('posts', { title, content });
revalidatePath('/blog');
}
// Client コンポーネントで Server Action を使用
function NewPostForm() {
return (
<form action={createPost}>
<input name="title" />
<textarea name="content" />
<button type="submit">公開</button>
</form>
);
}
4. React Compiler:自動パフォーマンス最適化
React Compiler(旧 React Forget)は自動的に memo ロジックを挿入し、手動の useMemo、useCallback、memo が不要になります。
コンパイル前
function ExpensiveComponent({ items, filter }) {
// 開発者が手動で最適化
const filtered = useMemo(
() => items.filter(i => i.category === filter),
[items, filter]
);
const handleClick = useCallback((id) => {
console.log(id);
}, []);
return <List items={filtered} onClick={handleClick} />;
}
コンパイル後(自動最適化)
function ExpensiveComponent({ items, filter }) {
// 直接書く、コンパイラが自動 memoize
const filtered = items.filter(i => i.category === filter);
const handleClick = (id) => console.log(id);
return <List items={filtered} onClick={handleClick} />;
}
Compiler の有効化
// next.config.js
const nextConfig = {
experimental: {
reactCompiler: true, // または 'unstable' で最新機能
},
};
Compiler の制限
| 自動最適化されないシナリオ | 理由 |
|---|---|
| 受け取った props/mutable オブジェクトの変更 | 副作用の追跡不可 |
| フック外で作成されたクロージャ | ライフサイクルが不明確 |
arguments オブジェクトの使用 |
非標準的な使用法 |
5. ref as prop:forwardRef にさようなら
React 18 の書き方
const Input = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
React 19 の書き方
function Input({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
// 使用例
<Input ref={inputRef} placeholder="入力してください" />;
6. Document Metadata
React 19 はコンポーネント内での <title>、<meta>、<link> 宣言をネイティブサポートします:
function BlogPost({ post }) {
return (
<>
<title>{post.title}</title>
<meta name="description" content={post.excerpt} />
<link rel="canonical" href={`https://example.com/blog/${post.slug}`} />
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
</>
);
}
React は自動的にこれらのタグを <head> に引き上げ、異なるルートの metadata を自動的に重複排除・置換します。
7. その他の改善点
useOptimistic:楽観的更新
function LikeButton({ postId, initialLiked }) {
const [liked, addOptimisticLike] = useOptimistic(initialLiked);
async function handleLike() {
addOptimisticLike(true); // 即座にいいねを表示
await likePost(postId); // バックグラウンドで同期
}
return <button onClick={handleLike}>{liked ? '❤️' : '🤍'}</button>;
}
useSyncExternalStore の改善
getSnapshot が異なるが意味的に等価な値を返すストア(キャッシュ付きデータ取得など)の購読をサポート。
Custom Elements 完全サポート
React 19 は Custom Elements の属性とイベントを適切に処理します:
<my-custom-element someProp="value" onCustomEvent={handler} />
移行チェックリスト
| 変更 | 影響 | アクション |
|---|---|---|
forwardRef → ref prop |
forwardRef を使用する全コンポーネント | 移行 |
useMemo/useCallback |
手動 memo | Compiler 有効化後に段階的に削除 |
onSubmit → action |
フォームコンポーネント | Actions にリファクタリング |
useContext → use() |
Context 消費 | 任意で移行 |
ref.current.cleanup() |
ref コールバッククリーンアップ | 新しいパターン |
| 文字列 ref 非推奨 | レガシーコード | コールバック/オブジェクト ref に移行 |
Codemod ツール
npx react-codemod@latest react-19
forwardRef 移行、文字列 ref 置換など、ほとんどの破壊的変更を自動処理します。
#React#React 19#Server Components#前端框架