react について
reactは、Reactコードの作成とレビューに使う実践ガイドです。Effect、レンダリング性能、データ取得、フォーム、React 19への移行を扱い、レビュー用チェックリストも含みます。
主な機能
- 01Effectの使用とクリーンアップの指針
- 02再レンダーと状態管理の助言
- 03データ取得とリクエスト並列化
- 04React 19のフォームと移行事項
- 05性能のヒントとレビュー項目
活用シーン
- 01不要なEffectの使用をコンポーネントで確認
- 02購読、リスナー、リクエストの後処理をレビュー
- 03データ取得とコンポーネント描画を改善
- 04React 19移行とフォーム変更を計画
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ xgent-ai/ skills --skill reactインストール後、Claude Code で/reactを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/actions.mdcomponent-patterns.mddata-fetching.mdeffect-patterns.mdjs-performance.mdreact19-migration.mdrendering-performance.mdrerender-optimization.md詳細
React のベストプラクティス
React コードを記述またはレビューする際は、以下のガイドラインを適用してください。
参考ファイル
同じターン内に、関連する参考資料をすべて並行して読んでください。フィードバックを行う際は、これらを引用してください。
- Effect のパターン:Effect が不要な場合、依存関係のルール、クリーンアップ、サブスクリプション、
useSyncExternalStore、一度限りの初期化 - 再レンダーの最適化:
memo/useMemo/useCallback、派生状態、関数型更新、遅延初期化、useDeferredValue、startTransition、useEffectEvent - コンポーネントのパターン:Ref、
useImperativeHandle、カスタムフックのルール、制御コンポーネントと非制御コンポーネント、props のバケツリレーよりコンポジションを優先すること、flushSync - データ取得:リクエストの並列化、Suspense 境界、
use()と安定した Promise ソース、リクエストの重複排除、パッシブリスナー、localStorageのバージョン管理 - レンダリングのパフォーマンス:
content-visibility、ハイドレーションの不一致、リソースヒント、スクリプトの読み込み、SVG アニメーション、Activity、useTransition - JS のパフォーマンス:レイアウトスラッシング、
Set/Mapの検索、インデックスマップ、単一パスの反復処理、toSorted、requestIdleCallback - アクション:
<form action>、useActionState、useFormStatus、useOptimistic— ミューテーションにおける保留状態、エラー状態、楽観的状態 - React 19 への移行:18 からのアップグレード — ルート API、
findDOMNode、forwardRef、defaultProps、レガシーコンテキスト、文字列 Ref、propTypes、JSX トランスフォーム、TypeScript 型、act/test-utils、StrictMode のテスト回数
Effect が不要な場合
Effect は React のエスケープハッチです。外部システムとの同期に使用します。外部システムが関係しない場合は、通常 Effect は不要です。
Need to respond to something?
├── User interaction (click, submit, drag)?
│ └── EVENT HANDLER
├── Props/state changed and need a derived value?
│ └── CALCULATE DURING RENDER
│ └── Measurably expensive? useMemo
├── Need to reset state when an identity prop changes?
│ └── key PROP on the component
└── Component appeared on screen, and there's an external system?
└── EFFECT, with cleanup
Effect が必要な場合: React 以外のウィジェットやブラウザー API、サブスクリプション(useSyncExternalStore を優先)、コンポーネントが表示されたことを契機に実行するアナリティクス、クリーンアップを伴うデータ取得(データライブラリを優先)。
Effect が不要な場合: レンダリング用のデータ変換、ユーザーイベントの処理、状態の導出、状態更新の連鎖、親への通知、状態のリセット。
クイックリファレンス
Effect
| 状況 | しないこと | すること |
|---|---|---|
| props/state から派生する状態 | useState + useEffect | レンダリング中に計算する |
| コストの高い計算 | キャッシュするために useEffect を使う | useMemo を使う |
| prop の変更時に状態をリセットする | useEffect + setState | key prop を使う |
| ユーザーイベントへの応答 | state を監視する useEffect | イベントハンドラーを使う |
| 変更を親に通知する | useEffect から onChange を呼び出す | イベントハンドラー内で呼び出す |
| 外部ストアを購読する | useEffect で手動購読する | useSyncExternalStore を使う |
| データを取得する | クリーンアップのない useEffect | ignore フラグまたはデータライブラリを使う |
| Effect が毎回のレンダーで再実行される | 依存配列にオブジェクト/関数を指定する | Effect 内で作成する |
| 依存関係が不足している | eslint-disable exhaustive-deps | 関数型更新または useEffectEvent を使う |
| アプリの一度限りの初期化 | useRef ガード | モジュールレベルのフラグ |
再レンダー
- コンポーネントを別のコンポーネント内で定義しないでください。レンダーのたびに再マウントされます
- 次の state が現在の state に依存する場合は、関数型の
setStateを使ってください - コストの高い初期値には
useState(() => expensive())を使ってください。通常の形式ではレンダーのたびに実行されます - 単純な真偽値やプリミティブ値の式を
useMemoでラップしないでください - 複数の処理をまとめた
useMemo/useEffectは分割し、それぞれ一つの関心事を扱うようにしてください - 頻繁に変化するがレンダリングされない値(マウス位置、フラグ)は Ref に保持してください
- React Compiler が有効な場合は、手動での
memo/useMemo/useCallbackを省略してください
データ取得
- 独立したリクエストには
Promise.all()を使い、依存するリクエストは項目ごとに順番に実行します - 早期リターンの後、または低コストの同期ガードの後に
awaitを移動します - コンポーネントのインスタンスごとではなく、エンドポイントごとに共有リクエストを1つ使います(SWR / React Query)
- すべての fetch エフェクトには
ignoreフラグまたはAbortControllerが必要です use()に渡す Promise は、ローダー、キャッシュ、ライブラリ、または Server Component から取得します。レンダー中に作成してはいけません
フォームとミューテーション(React 19)
onSubmit+preventDefaultより<form action={fn}>を、ローディング/エラーのリデューサーよりuseActionStateを使います- 想定されるエラーはアクションから状態として返し、スローされたエラーはエラーバウンダリに渡します
useFormStatusはreact-domからインポートし、親の<form>の状態だけを読み取りますuseOptimisticには確定済みの状態を渡し、Action 内でセッターを呼び出します- Action 内で
awaitの後に状態を更新する場合は、別のstartTransitionで囲みます
React 19 へのアップグレード
- まず
npx codemod@latest react/19/migration-recipeを実行します。アップグレード PR では API のみが変更されます forwardRefは引き続き動作します。refは通常の prop なので、必要に応じて変換しますdefaultPropsは関数コンポーネントでは無視されますが、クラスコンポーネントでは引き続き動作します- StrictMode では引き続きエフェクトが2回実行されます。変更されたのは、
useMemo/useCallbackの結果の再利用と、ref コールバックが2回呼び出される点です
パフォーマンス
- 最適化する前に測定します。推測せず、プロファイリングを行います
- DOM への書き込みをまとめてから一度だけ読み取ります。交互に行うとリフローが発生します
- 検索を繰り返す場合は
Set/Mapを使い、.filter().map()を連鎖させる代わりに1回の走査で処理します - props と state には
.toSorted()を使います。.sort()は変更を加えます requestIdleCallbackを使って、アナリティクスとプリフェッチを後回しにします
レビューチェックリスト
- すべての
useEffectは外部システムとの同期に使われていますか? そうでない場合は、代替方法を提案してください。 - 依存配列はすべて完全で、lint の抑制はありませんか?
- すべてのサブスクリプション、リスナー、タイマー、fetch にクリーンアップがありますか?
- 他の props や state から導出できる、冗長な state はありませんか?
- コンポーネントはモジュールスコープで定義されていますか?
- 独立した非同期呼び出しは並列化されていますか?
- props や state に対して、配列を変更するメソッドを使っていませんか?
use()に渡すすべての Promise は、レンダー間で安定していますか?- React 19 では、フォームは Action を使い、エラーを状態として返していますか? また、削除された API(
findDOMNode、文字列 ref、レガシーコンテキスト、test-utils)は残っていませんか?
コメント
Markdown 対応