mcpField
R
react-dev

react-dev

github.com/fixmyberlin開発065 回インストール3 日前に更新
リポジトリ

react-dev について

FixMyBerlin/FMC の React・TypeScript コンポーネント規約をまとめたスキルで、型付けと `useEffect` の適切な使用を中心に扱います。React コードを書く開発者やレビュー担当者向けで、ルーティングやサーバー処理は関連スキルを案内します。

主な機能

  1. 01React 19 のコンポーネントと ref の型付け
  2. 02名前付き `useEffect` 関数
  3. 03Effect を避ける場面の指針
  4. 04React Compiler と Oxlint の規約
  5. 05React 19 API の利用メモ

活用シーン

  1. 01コンポーネントの props とイベント処理の型付け
  2. 02Effect のロジックの作成やレビュー
  3. 03派生状態やデータ取得での Effect 回避
  4. 04React Compiler と lint の規約適用

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/fixmyberlin/fixmyskills --skill react-dev

インストール後、Claude Code で/react-devを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

examples/
generic-components.md
references/
effects.md
event-handlers.md
react-19-patterns.md
tanstack-router.md

詳細

LLM リファレンス: react.dev/llms.txt · tanstack.com/llms.txt · 主なエフェクトのページ:エフェクトが不要な場合もあります

React + TypeScript (FMC)

React の型付けとuseEffect の使用方針(命名、スコープ、使用を避ける場合)に関する FMC の規約です。ルーティングとサーバー I/O については、関連するスキル(以下)で扱います。

FMC スタック(必須)

要件ルール
React 1919.x を対象とします。新しいコードでは forwardRef / useFormState / useActionState を使用しません。フォームには TanStack Form を使用します。
React Compilerアプリのビルドで有効化します。自動メモ化がデフォルトです。
LintOxlint の react プラグインを使用します。Compiler のネイティブルールはデフォルトで有効で、さらに 'react/unsupported-syntax': 'error' を設定します。eslint-plugin-react-hooks の jsPlugin は使用しません。
メモ化デフォルトでは useMemo / useCallback / memo を追加しないでください。プロファイリングで必要と判明した場合、または lint ルールで必要な場合にのみ追加します。
TanStack Startサーバー I/O とミューテーション → tanstack-start-conventions(このスキルではコンポーネントの型付けのみを扱います)
データ取得ルートローダー + React Query を使用します。useEffect での fetch は使用しません(tanstack-router-conventions を参照)。

ドキュメント:React Compiler · React のルール · Oxc React Compiler サポート

関連スキル

トピックスキル
ルート、ローダー、validateSearchtanstack-router-conventions
URL の状態(ルーターの検索を優先)tanstack-router-conventions
SSR、サーバー関数、Start のレイアウトtanstack-start-conventions
フォルダー構成、薄いルート(Start)スキル tanstack-start-conventions → references/app-structure.md
createServerFn、サーバーミューテーションスキル tanstack-start-conventions → references/server-functions.md
クライアントストア(context + reducer ではなく)zustand-state-management
セマンティック HTML(残った div/span)スキル unslop-code → references/semantic-html.md

型付けに関する注意点

  • Props: React.ComponentPropsWithoutRef<'button'>(ref を除外)でネイティブ要素を拡張します。children: React.ReactNode を使い、JSX.Element は使わないでください。
  • バリアントの props: 判別可能なユニオン({ variant: 'link'; href: string } | { variant: 'button'; onClick: () => void })を使い、判別子で型を絞り込みます。
  • ref: React 19 では通常の prop です。新たに forwardRef を使う必要はありません → react-19-patterns.md。
  • イベント: currentTarget に型が付くよう、具体的な React.*Event<HTMLElement> 型を使います。any は使わないでください → event-handlers.md。
  • フック: null、[]、ユニオンには、useState<User | null>(null) のように型を明示します。DOM には useRef<HTMLInputElement>(null) と ?. を、変更可能な値を保持するボックスには useRef(0) を使います。useReducer のアクションには判別可能なユニオンを使い、createContext<T | null>(null) と例外を投げるカスタムフックを組み合わせます。外部ストアには useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) を使います。
  • ルートフック: createFileRoute コンポーネント内で Route.useParams() / Route.useSearch() を使います。validateSearch はルートファイル内に記述します → tanstack-router.md。

useEffect — 命名、スコープ、使用を避ける場合

エフェクトは、外部システム(React 以外のウィジェット、ブラウザー API、マップ SDK、サブスクリプション、分析)との同期に使うための最終手段です。外部システムが関係しない場合、通常はエフェクトを使うべきではありません。

すべての useEffect に名前を付ける

useEffect には、無名のアロー関数ではなく、必ず名前付き関数式を渡します。カスタムフック内のエフェクトを含め、新規コードと編集するコードではこのスタイルを標準とします。複雑なクリーンアップ関数にも名前を付けます。

useEffect(
  function updateDocumentTitle() {
    document.title = `${count} items`
  },
  [count],
)

useEffect(function pollServerForUpdates() {
  const intervalId = setInterval(/* ... */, 5000);
  return function stopPollingServer() {
    clearInterval(intervalId);
  };
}, [serverId]);
命名からわかる兆候

命名は、キーボードに向かった状態で行う設計レビューです。詳細はeffects.mdを参照してください。

シグナル意味修正
名前に**「and」/「also」**が必要1つのエフェクトに無関係な関心事が含まれているそれぞれ1つの名前で表せるよう、エフェクトを分割します
syncDerivedValue、updateStateFromState、setXBasedOnY派生状態または状態間の同期レンダリング中に導出します
notifyParentOfChange、reportStateToParent子の状態をきっかけに親が更新されるイベントハンドラーで呼び出す、データを上位に持ち上げる、またはコンポーネントを制御されたものにします
resetFormOnSubmitFlag状態の受け渡しでユーザーの意図を表現イベントハンドラーで処理します
persistOnClose、syncWhenClosed、saveDraftOnDismiss閉じる操作/UI状態の開閉に伴う副作用ハンドラーを使います。isOpen に対する Effect ではありません(effects.md §3)
明確な外部操作を表す動詞:connectTo…、subscribeTo…、initialize…、synchronize…(ブラウザー、ネットワーク、マップ SDK)Effect が正当な場合が多いそれでも名前を付け、必要に応じてクリーンアップを追加します

正直な名前が React 内部の状態管理のように聞こえるなら、そのコードはレンダリング中、イベントハンドラー、または別のパターンに置くべきです。

クイックリファレンス
状況してはいけないことすること
props/state から派生する状態useState + useEffectレンダリング中に計算する(デフォルトでは useMemo を使いません。Compiler は有効です)
prop の変更時に状態をリセットuseEffect と setStatekey prop
ユーザーイベントへの応答状態を監視する useEffectイベントハンドラーから直接処理する
閉じたときの永続化/同期isOpen を監視する useEffect閉じるハンドラー(または onCloseComplete)
変更を親に通知するonChange を呼び出す useEffectイベントハンドラーから呼び出すか、制御コンポーネントを使う
子から親へのデータ渡しonFetched を呼び出す Effect親がフェッチして下位に渡す
外部ストアEffect + useStateuseSyncExternalStore
データのフェッチuseEffectルートローダー + React Query

Strict Mode(開発時): マウント時に Effect のセットアップが 2 回実行されます。サブスクリプションとタイマーにはクリーンアップを追加してください。初回のみの初期化にはガードを設けてください(モジュールレベルの didInit ガード。 effects.md §6 を参照)。

Effect と React Compiler/lint
  • Compiler は外部との同期に使う Effect を置き換えるものではありません。メモ化の変更によって Effect が再実行されるタイミングが変わる場合があります。Compiler を無効にするのではなく、Effect の設計(依存関係、分割、useEffectEvent)を修正してください。
  • lint:Oxlint のネイティブ React Compiler ルール(react/set-state-in-effect、react/immutability、…)。
useEffectEvent

コールバックの一部で最新の props/state を読み取りながら、サブスクリプション(接続、インターバル、リスナー)を維持する必要がある Effect に使用します。例:effects.md §7。

  • ユーザーに見えるイベントのような名前にします:onConnected、onTick など。onMount/onUpdate は避けてください。
  • 呼び出せるのは Effect(または同じコンポーネント内の他の Effect Event)からのみです。レンダリング中、イベントハンドラー内、子への props としては使わないでください。
  • 依存配列から省略します(lint によって強制されます)。Effect を再実行すべき依存関係を隠すために使ってはいけません。

React 19 の API(参照先)

API用途ドキュメント
use()Promise/コンテキストの値を取り出す(サスペンドすることがあります)use
useOptimistic楽観的 UIuseOptimistic
useTransition緊急性の低い更新useTransition
useEffectEventEffect 内で安定したコールバックuseEffectEvent

ルール

必ず守ること

  • 名前付きの useEffect 関数を使います。React Compiler を有効にし、Oxlint のネイティブ react/* Compiler ルールを使います。
  • 汎用的な div/span より意味的な HTML を優先します。スキル unslop-code → references/semantic-html.md
  • React 19 では ref を prop として使います。

決してしないこと

  • 新たに forwardRef/useFormState/useActionState を使う(フォームには TanStack Form を使います)
  • 明確な理由なく、デフォルトで useMemo/useCallback/memo を使う
  • アプリのデータ取得に useEffect を使う(ローダー/Query を使います)
  • ストリーミングへの引き渡しで use() に渡す Promise を await する

参考資料

  • effects.md — useEffect を記述またはレビューするとき、またはエフェクト名が上記の問題点一覧に該当するときに参照します(key によるリセット、ジェスチャー時の永続化、親からのデータフロー、初期化ガード、useEffectEvent の例)
  • event-handlers.md — クリック/送信/変更以外のイベントハンドラーの型を指定するとき、またはイベントを props 経由で転送するときに参照します
  • react-19-patterns.md — ref を props として型指定するとき、use() を使うとき、またはレガシーなコードベースを React 19 に移行するときに参照します
  • generic-components.md — ジェネリックコンポーネントを記述するときに参照します(HasId で制約した T extends HasId、アクセサーを使った Select<T>)
  • tanstack-router.md — ルートフックを型指定するときに参照します(標準参照先:tanstack-router-conventions → router-typescript.md)
  • Neciu Dan — useEffect 関数に名前を付け始めましょう

コメント