react について
AIエージェント向けのReact 19ベストプラクティススキルです。9カテゴリ49ルールで、コンポーネントの指針と体系的なコードベース監査を扱います。
主な機能
- 019カテゴリ49ルール
- 02React 19のパターンとAPI
- 03パターン認識の例
- 04体系的な複数ファイルレビュー手順
- 05コードベース衛生チェック
活用シーン
- 01Reactコンポーネントの作成やリファクタリング
- 02React 18からReact 19への移行
- 03Reactリポジトリの性能や設計上の問題の監査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pproenca/ dot-skills --skill reactインストール後、Claude Code で/reactを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
AGENTS.mdmetadata.jsonassets/templates/_template.mdreferences/_review-algorithm.md_sections.mdconc-activity-component.mdconc-automatic-batching.mdconc-concurrent-safe.mdconc-suspense-fallback.mdconc-use-deferred-value.mdconc-use-transition.mdcross-boundary-coherence.mdcross-component-consolidation.mdcross-dead-code.mdcross-extract-shared-logic.mdcross-prop-shape-drift.mddata-cache-deduplication.mddata-document-metadata.mddata-error-boundaries.mddata-parallel-fetching.mddata-resource-hints.mddata-suspense-data-fetching.mddata-use-hook.mdeffect-avoid-unnecessary.mdeffect-cleanup.mdeffect-object-dependencies.mdeffect-use-effect-event.mdeffect-use-sync-external-store.mdform-actions.mdform-use-action-state.md詳細
React 19 のベストプラクティス
AI エージェント向けの、React 19/19.2 に関する包括的なベストプラクティスガイドです。影響度の高いもの(並行レンダリング、サーバーコンポーネント)から、コードベース全体に関わる整備(重複排除、デッドコード、境界の一貫性)まで、優先度順に並べた 9 カテゴリ・49 個のルールを収録しています。React 19 の主な変更点である、通常のプロパティとしての ref(forwardRef は非推奨)、ネイティブのドキュメントメタデータ、リソースのプリロード API、useActionState、useOptimistic、use() フック、プロバイダーとしての <Context> を反映しています。
各ルールファイルでは、API 名ではなく パターンの形を説明し、同じ問題がどのような構文上の形で現れるかを 2~4 個挙げた 「認識すべきパターン」 セクションから始まります。特に価値の高いルール(実際のコードベースでよく見られる形の問題を扱うもの。フォームアクション、プロパティとしての ref、派生状態、コンテキスト、use() フック、useCallback/memo の組み合わせなど)には、grep で見つけやすいケースだけでなくパターン検出を学べるよう、具体的な 「別の形で現れる例」 の誤った例/正しい例のペアも追加されています。
適用する場面
- 新しい React コンポーネントを作成するとき、または既存のコンポーネントをリファクタリングするとき
- ディレクトリ、PR、リポジトリ全体を監査または最新化するとき(必須の手順については
references/_review-algorithm.mdを参照) - React 18 から React 19 に移行するとき(forwardRef → プロパティとしての ref、
<Context.Provider>→<Context>、useFormState→useActionState) - 再レンダーのパフォーマンスやバンドルサイズを最適化するとき
- 並行機能(useTransition、useDeferredValue、Activity)を使用するとき
- サーバーコンポーネントやサーバー/クライアント境界を設定するとき
- フォームアクション、楽観的更新、データ取得を実装するとき
- 自動メモ化のために React Compiler を設定するとき
- React コードをレビューし、よくあるアンチパターンや古い React 18 の慣用表現を確認するとき
- 単一ファイルのルールでは見つけられない、コードベース全体に関わる問題(ファイル間のロジックの重複、よく似たコンポーネント、デッドコード、クライアントである必要のない
'use client'ファイル、プロパティ形状の不整合など)を見つけるとき(カテゴリ 9 を参照)
コードベースをレビューまたはリファクタリングする方法
ユーザーから React コード(単一ファイルでもリポジトリ全体でも)のレビュー、リファクタリング、最新化、監査を依頼された場合は、references/_review-algorithm.md に従ってください。独自のやり方で進めないでください。
このドキュメントに記載された、必ず守るべき 4 つの事項:
- 2 つのモードを使い分ける。リポジトリ全体の監査を拒否しない。 モード A(対象を絞る。約 20 ファイル以下)または モード B(ツリー全体:一覧作成、対象を絞った横断調査、カテゴリ 9 全体の確認)を選択します。800 ファイルをコンテキストに詰め込まずに「コードベースを監査して」という依頼に対応する方法は、このアルゴリズムで定められています。
- grep よりも判断を優先する。 各ルールでは、構文上の目印ではなく パターンの形を定義しています。調査を始める前に、各ルールの 「認識すべきパターン」 セクションを読んでください。grep で見つかるのは簡単な違反であり、価値の高い問題(
forwardRefを避けるためにコールバック ref を手作業で段階的に渡しているケース、useActionStateの役割を果たすonSubmit、派生状態のような形になっているuseState+useEffect、取得処理の一連の流れを隠しているカスタムフックなど)は見落とします。grep は きっかけであり、判定ではありません。 - ファイル単位ではなくカテゴリ単位で進め、確認を徹底する。 優先度順(CRITICAL → … → CROSS-CUTTING)に、対象となるすべてのファイルをカテゴリごとに調査します。このアルゴリズムでは、対象範囲の宣言、カテゴリごとの進捗行、最後に 網羅状況の表(
category × file、セルの値は{clean, N findings, n/a}のいずれか)が必須です。出力にカテゴリが欠けていれば、すぐに分かります。 - コードベース全体に関わる問題はカテゴリ 9 から見つける。 単一ファイルのルールだけでは、「この 2 つのコンポーネントは統合すべき」や「このフックは使われていない」とは判断できません。カテゴリ 9(コードベースの整備)では最後に一覧全体を調査し、削除/重複排除/再利用/統合に関する指摘をまとめます。
単一ファイルに関する個別の質問(「このフックは問題ないですか?」など)は、該当するルールを直接参照できます。このアルゴリズムは、複数ファイルやリポジトリ全体を対象とする場合のためにあります。
ルールのカテゴリ
| # | カテゴリ | 影響度 | ルール数 | 主なトピック |
|---|---|---|---|---|
| 1 | 並行レンダリング | CRITICAL | 6 | useTransition、useDeferredValue、Activity、バッチ処理、レンダーの純粋性 |
| 2 | サーバーコンポーネント | CRITICAL | 6 | RSC の境界、データ取得、ストリーミング、シリアライズ可能な props |
| 3 | アクションとフォーム | HIGH | 5 | フォームアクション、宣言的なフォーム状態、useOptimistic、サーバー側の検証 |
| 4 | データ取得 | HIGH | 7 | use() フック、cache()、Suspense、ドキュメントメタデータ、リソースヒント |
| 5 | 状態管理 | MEDIUM-HIGH | 5 | 派生値、コンテキストの分割、関数型更新、reducer |
| 6 | メモ化とパフォーマンス | MEDIUM | 5 | React Compiler、useMemo、useCallback、React.memo |
| 7 | エフェクトとイベント | MEDIUM | 5 | useEffectEvent、クリーンアップ、外部ストア、派生状態のアンチパターン |
| 8 | コンポーネントパターン | LOW-MEDIUM | 5 | ref を prop として渡す、コンポジション、制御コンポーネントと非制御コンポーネント、key によるリセット |
| 9 | コードベースの健全性 | 横断的 | 5 | 重複排除、統合、不要なコード、境界の一貫性、prop の形状のばらつき |
クイックリファレンス
重要なパターン — まずこれらを正しく適用してください。
- クライアントコンポーネントではなく、サーバーコンポーネントでデータを取得する
'use client'の境界は可能な限り下位に配置する- 時間のかかるノンブロッキング更新には
startTransitionを使う - タブやページの切り替えをまたいで状態を保持するには
<Activity>を使う
React 19 の最新イディオム(React 18 のパターンは生成しないでください):
function C({ ref, ...props })—forwardRefでラップしない<MyContext value={v}>—<MyContext.Provider>を使わないuseActionState—useFormStateを使わないuseRef<T>(null)— 必ず初期値を渡す<title>、<meta>、<link>をインラインでレンダーする —react-helmetを使わないreact-domのpreload/preconnect—<link rel="preload">を手動でレンダーしない
よくある単一ファイルの誤り — こうしたアンチパターンを避けてください。
- クライアントコンポーネント内で
use()用のプロミスを作成する(無限ループの原因になります) - すべてをメモ化する(代わりに React Compiler v1.0+ を使う)
- 派生状態、ミューテーション、親への通知、アプリの初期化にエフェクトを使う
- コンポーネントツリー内の高すぎる位置に
'use client'を配置する
コードベースレベルのパターン — カテゴリ 9 の一斉チェックで次の点を確認してください。
- インポート元が 0 件のコンポーネント/フック/ユーティリティ — 削除する
- 同じエフェクト/状態の形状を持つファイルが 2 つ以上ある — 共有フックを抽出する
- ラベル/アイコンにばらつきのある構造上同一のコンポーネントが 2 つ以上ある — バリアントまたはコンポジションを使って統合する
- フックの使用にクライアント側での実行が必要ない
'use client'ファイル — サーバーコンポーネントに降格する(またはサーバー側の親コンポーネントとクライアント側のアイランドに分割する) - コンポーネント間で異なる名前が使われている、同じ概念を表す prop — 正式な名前に統一する
目次
- 並行レンダリング — CRITICAL
- 1.1 アンマウントする代わりに、ナビゲーションをまたいで非表示のサブツリーの状態を保持する — HIGH(
<Activity>) - 1.2 更新をトランジションで囲み、ナビゲーションをまたいで以前のコンテンツを表示し続ける — HIGH
- 1.3 自動バッチ処理を信頼する —
flushSyncやunstable_batchedUpdatesに頼らない — HIGH - 1.4 所有していない値が高コストな子の再レンダリングを引き起こす場合、その値の更新を遅らせる — CRITICAL(
useDeferredValue) - 1.5 高コストな状態更新を低優先度としてマークし、入力への応答性を保つ — CRITICAL(
useTransition) - 1.6 レンダーを純粋に保つ — レンダー中に変更、サブスクライブ、外部状態の読み取りを行わない — MEDIUM-HIGH
- 1.1 アンマウントする代わりに、ナビゲーションをまたいで非表示のサブツリーの状態を保持する — HIGH(
- サーバーコンポーネント — CRITICAL
- 2.1 ブラウザー API に依存するライブラリをクライアントコンポーネントのラッパー内に隔離する — MEDIUM-HIGH
- 2.2 時間のかかる非同期処理を独自の Suspense 境界の内側に分離し、高速なコンテンツを先にストリーミングする — MEDIUM-HIGH
- 2.3 サーバーで async/await を使ってデータを取得する — クライアントコンポーネントで
useEffect+fetchを使わない — CRITICAL - 2.4
'use client'の境界はルートではなく、インタラクティブな末端コンポーネントまで下げる — CRITICAL - 2.5 サーバーからクライアントへの境界を越えられるのは、RSC ワイヤ形式でエンコードできるデータのみ — HIGH
- 2.6 サーバーコンテンツはインポートするのではなく、
childrenまたは名前付きスロットを介してクライアントコンポーネントの内側に渡す — HIGH
- アクションとフォーム — HIGH
- 3.1 フォームの送信には、JS のみの
onSubmitハンドラーではなくactionプロパティを使う — HIGH - 3.2 命令型の pending/error/submit 管理を、単一の宣言型フォーム状態フックにまとめる — HIGH(
useActionState) - 3.3 送信ボタンは、プロパティとして渡された値ではなく、コンテキストから親フォームの pending 状態を読み取る — MEDIUM-HIGH(
useFormStatus) - 3.4 ミューテーション後の結果をすぐに表示し、失敗時は自動的にロールバックする — HIGH(
useOptimistic) - 3.5 バリデーションはサーバーアクションの役割とする。クライアント側のチェックは拡張機能であり、唯一の防御策にしない — MEDIUM
- 3.1 フォームの送信には、JS のみの
- データ取得 — HIGH
- 4.1 独立したデータ取得は並行して実行する —
awaitの逐次実行はウォーターフォールになる — MEDIUM-HIGH - 4.2 リクエストごとにデータ取得関数をメモ化し、同じデータを読む複数のコンポーネントが再取得しないようにする — HIGH(
cache()) - 4.3 各 Suspense 境界を Error Boundary で囲む — 失敗を適切に処理できるようにする — MEDIUM
- 4.4 ローディング状態は Suspense のフォールバックとして宣言し、
if (loading) return …で組み立てない — HIGH - 4.5
useEffect+useStateでつなぎ合わせるのではなく、use()でプロミスや条件付きコンテキストを読み取る — HIGH(use()) - 4.6 ページのメタデータは
<title>/<meta>/<link>としてインラインでレンダーする — Helmet 系の head 管理ライブラリは使わない — MEDIUM - 4.7
<link rel="preload">を手動でレンダーするのではなく、react-domの命令型リソースヒント API を使う — MEDIUM
- 4.1 独立したデータ取得は並行して実行する —
- 状態管理 — MEDIUM-HIGH
- 5.1 派生値はレンダー本体で計算する — 別の状態に複製しない — MEDIUM
- 5.2 各コンテキストは独立して変化する状態を1つだけ保持する — 肥大化したコンテキストは分割する — MEDIUM
- 5.3 次の状態が前の状態に依存する場合は
setX(prev => …)を渡す —setX(x + 1)は使わない — MEDIUM-HIGH - 5.4 初期値の計算にコストがかかる場合は
useStateに関数を渡す — インラインで計算しない — MEDIUM-HIGH - 5.5 複数フィールドにまたがる連携した状態遷移は、兄弟関係にある N 個の
useStateセルではなく、単一の reducer にまとめる — MEDIUM(useReducer)
- メモ化とパフォーマンス — MEDIUM
- 6.1 測定したベースラインをもとにメモ化する — すべての値やコールバックを
useMemo/useCallbackでむやみにラップしない — MEDIUM - 6.2 React Compiler v1.0 を導入する — ビルド時のメモ化に任せ、手動の
useMemo/useCallbackによる不要な記述を取り除く — MEDIUM - 6.3 高コストで純粋なコンポーネントは、プロパティが実際に安定している場合にのみ
memo()でラップする — MEDIUM - 6.4 下流でコールバックの同一性の安定性が必要な場合にのみ、その同一性を安定させる — MEDIUM(
useCallback) - 6.5 入力が安定していて、処理のコストが測定可能なほど高い場合にのみ、レンダー間で計算結果をキャッシュする — MEDIUM(
useMemo)
- 6.1 測定したベースラインをもとにメモ化する — すべての値やコールバックを
- エフェクトとイベント — MEDIUM
- 7.1 サブスクライブ、スケジュール、接続を行うすべてのエフェクトで、解除や切断を行うクリーンアップを返す — MEDIUM
- 7.2
useEffectは外部システムとの同期に使う — 派生状態、変更、イベントロジック、親への通知、アプリの初期化には使わない — HIGH - 7.3 エフェクトの依存関係は参照で比較される — レンダー中に構築したオブジェクトや配列ではなく、プリミティブを渡す — MEDIUM
- 7.4 値の変化による再サブスクライブを行わずに、エフェクトのコールバック内で最新のプロパティや状態を読み取る — MEDIUM(
useEffectEvent) - 7.5
useEffect+useStateではなく、useSyncExternalStoreを使って外部の可変状態をサブスクライブする — MEDIUM
- コンポーネントのパターン — LOW-MEDIUM
- 8.1 コンポーネントは
refを通常の分割代入可能なプロパティとして受け取る —forwardRefラッパーをなくし、受け渡しをやめる — MEDIUM-HIGH - 8.2 変更のたびに値を読み取る必要がある場合にのみ制御コンポーネントを使い、それ以外では
<form action>による非制御コンポーネントを優先する — LOW-MEDIUM - 8.3 任意のスロットが多く、プロパティ数が約6個を超えたら、代わりに
childrenを受け取り、呼び出し側で組み立てられるようにする — LOW-MEDIUM - 8.4
key={entity.id}を設定して、状態を持つ子の同一性を編集対象のエンティティに結び付ける — 古い状態の破棄は React に任せる — LOW-MEDIUM - 8.5 親が レンダー方法 を制御する必要がある場合にのみレンダープロパティを使う — ロジックの再利用にはカスタムフックを優先する — LOW-MEDIUM
- 8.1 コンポーネントは
- コードベースの整理 — CROSS-CUTTING(複数ファイルにまたがる指摘。リポジトリ全体の監査に必要)
- 9.1 重複するエフェクト/状態の構造を共有フックに切り出す — HIGH
- 9.2 類似したコンポーネントを、バリアントまたは合成を用いた1つのコンポーネントにまとめる — HIGH
- 9.3 インポート元がないコンポーネント、フック、ユーティリティを削除する — MEDIUM-HIGH
- 9.4 フックの使用にクライアントが必要ない
'use client'ファイルは、クライアント境界から外す — HIGH - 9.5 コンポーネント間で同じ概念に異なるプロパティ名が使われている場合、標準の名前に統一する — MEDIUM-HIGH
参考資料
- https://react.dev
- https://react.dev/blog/2024/04/25/react-19-upgrade-guide
- https://react.dev/blog/2024/12/05/react-19
- https://react.dev/blog/2025/10/01/react-19-2
- https://react.dev/blog/2025/10/07/react-compiler-1
- https://react.dev/learn/you-might-not-need-an-effect
- https://github.com/facebook/react
関連スキル
- Next.js 16 App Router については、
nextjs-16-app-routerスキルを参照してください - クライアント側のフォーム処理については、
react-hook-formスキルを参照してください - TanStack Query を使ったデータのキャッシュについては、
tanstack-queryスキルを参照してください