react について
React 18/19 のコンポーネントを作成・変更する際の規約をまとめたスキルです。状態、Effect、アクセシビリティ、テストを扱い、依頼がない限り未変更ファイルの再構成は求めません。
主な機能
- 01Server Component を標準にする方針
- 02状態と Effect の指針
- 03エラー境界と Suspense 境界
- 04React 19 API の規約
- 05アクセシブルなマークアップとテスト
活用シーン
- 01React コンポーネント変更のレビュー
- 02コールバック内の古い状態の回避
- 03ローディング表示の配置決定
- 04アクセシブルなロールによる操作要素のテスト
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ alexander-danilenko/ cortex-ai-skills --skill reactインストール後、Claude Code で/reactを入力して読み込まれたか確認します。
詳細
React
React 18/19 向けのチーム内規約です。作成または変更するコンポーネントに適用してください。依頼がない限り、変更していないファイルまでこの規約に合わせてリファクタリングしないでください。
規約
- デフォルトではサーバーコンポーネントを使い、必要な箇所でのみ
'use client'を指定します — 状態、エフェクト、イベントハンドラー、ブラウザー API が必要な場合です。境界は可能な限りツリーの下層に配置してください。'use client'マーカーより上にあるコンポーネントはすべてブラウザーにも送られます。その境界を越えるものはすべてシリアライズ可能でなければなりません。関数、クラスインスタンス、または props オブジェクト内のDateは、ビルド時ではなく実行時にエラーになります。 - レンダーの終了後も存続するものの内部では、関数型アップデーターを使って状態を読み取ります — インターバル、サブスクリプション、デバウンスされたコールバックなどです。
useEffect(…, [])内のsetCount(count + 1)は初回レンダー時のcountをずっと保持するため、毎回エラーなく1に設定されます。setCount(c => c + 1)なら常に最新の状態を参照できます。 - エフェクトは、React の外部にあるものと同期するために使います — サブスクリプション、タイマー、React 以外のウィジェットなどです。データの変換はレンダー時に行い、派生値は通常の変数に格納し、イベントへの応答はハンドラーで処理します。
useEffectのバグの多くは、そもそも必要のないエフェクトが原因です。 - 何かを開始するすべてのエフェクトは、それを停止するクリーンアップを返します。 開発時に Strict モードがエフェクトを二重に呼び出すのは、クリーンアップの不足を明らかにするためです。これを単なるノイズではなく、そのまま警告として受け止めてください。
- キーには位置ではなく、安定した識別情報を使います。 配列のインデックスをキーにすると、リストの並べ替え時に React が誤った DOM ノードを再利用します。その結果、状態が誤った行に紐付く症状が現れます。
- 測定に基づく理由がある場合にメモ化します。
memo、useMemo、useCallbackはいずれも比較処理のコストがかかり、コードの読み取りも難しくします。本当に負荷の高い子コンポーネントや、それ自体がメモ化されていて新しい参照によってメモ化が無効になる子コンポーネントには有効ですが、デフォルトで付けるものではありません。 - 状態は適切な階層に置きます。
useStateはローカルで使い、共有する祖先の階層までに限って持ち上げます。クライアント側に本当にグローバルな状態がある場合は Zustand を使い、サーバー状態には TanStack Query を使います。キャッシュの無効化と再フェッチは TanStack Query の役割であり、エフェクトで自前実装すると気付かないうちに不具合が起きます。 - 独立して失敗する可能性があるものには、エラーバウンダリーを設けます — ルート、ウィジェット、サードパーティーの埋め込みなどです。エラーバウンダリーがないと、レンダーエラーによってツリー全体がアンマウントされ、ユーザーには空白のページが表示されます。
- フォールバックを表示したい場所に Suspense バウンダリーを配置し、置き換え後のレイアウトに合った読み込み UI を表示します。 ルートにバウンダリーを置くと、保留中のフェッチのたびにページ全体がスピナーになります。
- React 19:ミューテーションには
useActionStateと<form action>を、即時フィードバックにはuseOptimisticを、条件付きで Promise やコンテキストを読み取るにはuse()を使います。refは通常の props になったため、forwardRefは不要です。useFormStatusが状態を報告するのは、そのコンポーネントより上にあるフォームのみです。そのため、保留状態を読み取る送信ボタンは、<form>内にネストされた独自のコンポーネントにする必要があります。フォームをレンダーするコンポーネント内で呼び出すと、常にpending: falseが返されます。 - キーストロークによって負荷の高い処理が起きる場合は
useTransitionを使います。 入力の更新を緊急処理として行い、派生処理をトランジションとしてマークすれば、React がその処理を中断できます。これをしないと、大きなリストを絞り込むフィールドへの入力が、何も起きていないのに壊れているように感じられます。 - まずセマンティック HTML を使い、ARIA は不足を補う場合にのみ使います。
<button>なら、フォーカス処理、キーボード操作、ロールがそのまま利用できます。<div role="button">を使う場合は、その3つをすべて正しく再実装する必要があります。 - テストではテスト ID ではなく、ロールとラベルで要素を検索します。
getByRole('button', { name: /submit/i })は、ユーザーが要素に到達する方法で操作できなくなると失敗します。テストで検出したいのは、そのバグです。getByTestIdはそうした場合でも常に成功するため、アクセシブルな名前を持たない要素に限って代替手段として使います。
コメント
Markdown 対応