mcpField
R
remix-v2-forms-review

remix-v2-forms-review

github.com/existential-birdsテスト・品質8541 回インストール11 週間前に更新
リポジトリ

remix-v2-forms-review について

Remix v2 のフォームをレビューするスキルです。送信方法、処理中状態、アップロード、入力検証、複数アクションのルート構成を確認し、状況別ルールと検証手順で誤検出を抑えます。

主な機能

  1. 01Form と fetcher の使用確認
  2. 02処理中状態のレビュー
  3. 03アップロードと FormData の検証確認
  4. 04複数アクションのルート構成確認
  5. 05根拠と例外の検証手順

活用シーン

  1. 01Remix フォーム変更のレビュー
  2. 02ルート action を迂回する変更の検出
  3. 03行ごとの処理中表示の確認
  4. 04アップロードと入力検証の監査

インストール

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

$npx skills add https://github.com/existential-birds/beagle --skill remix-v2-forms-review

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

同梱ファイル

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

references/
form-vs-fetcher.md
multi-action-routes.md
pending-state.md
uploads-validation.md

詳細

Remix v2 フォームのコードレビュー

標準的なパターンについては、remix-v2-forms を参照してください。このスキルでは違反を指摘し、姉妹スキルではパターンを説明します。

クイックリファレンス

問題の種類参照先
手動の fetch()、ネイティブの <form>、<Form> と useFetcher の誤った選択references/form-vs-fetcher.md
useState による読み込みフラグ、行単位の処理に useNavigation を使用、保留中の状態の欠落references/pending-state.md
メモリ使用量に上限のないアップロード、encType の欠落、検証されていない FormData、ミラーリングされた楽観的状態references/uploads-validation.md
インテントパターンを使わずルートが増え続ける、PE フォールバックなしの PUT/DELETEreferences/multi-action-routes.md

レビューチェックリスト

  • アプリ内の変更には <Form> または <fetcher.Form> を使用し、fetch() / axios は使用しない
  • POST による変更では、ネイティブの <form> ではなく @remix-run/react から <Form> をインポートする
  • URL を変更しない場合(行の切り替え、インライン編集)には useFetcher を使用する
  • URL を変更する場合(作成、削除後に一覧へ戻る)には <Form> と redirect(...) を使用する
  • 保留中の状態は useNavigation() または fetcher.state から導出し、useState は使用しない
  • 行単位の保留中の状態には、ページ全体の useNavigation ではなく行ごとの fetcher.state を使用する
  • useNavigation() の呼び出しでは navigation.formAction を確認し、想定されるパスに対象を限定する
  • 楽観的 UI は fetcher.formData / navigation.formData を直接読み取り、ミラーリングしない
  • アクションが成功した場合は redirect(...) を返し、json() を返すのはエラー時または同じページにとどまる場合のみ
  • ファイルアップロードを行うすべてのフォームで <Form encType="multipart/form-data"> を使用する
  • unstable_createMemoryUploadHandler には必ず maxPartSize を指定し、大きなファイルにはディスク/ストリームハンドラーを使用する
  • FormData の値は DB に渡す前に検証/型変換し、form.get(x) as string のようなコードは使用しない
  • 1 つのルートに複数の変更がある場合は、別々のルートではなくインテントパターンを使用する
  • method="put|patch|delete" は JavaScript 専用であることを明記するか、POST とインテントの組み合わせに書き換える
  • nav.formMethod / fetcher.formMethod は大文字の文字列("POST"、"GET")と比較する。v2 の v2_normalizeFormMethod はデフォルトで大文字を返すため、=== "post" は一致しません。

有効なパターン(指摘しない)

以下は Remix v2 の正しい使い方であり、報告すべきではありません。

  • action プロパティのない <Form> — 慣例により現在の URL に POST します。action の明示は任意です。
  • GET の <Form> — 検索/フィルター UI に適しています。フォームのフィールドを URL の検索パラメーターとして loader に渡し、action は呼び出しません。ほとんどの「衛生」ルール(intent、redirect、encType)は POST フォームにのみ適用されます。
  • 1 ページで複数の useFetcher() インスタンスを使用する — 呼び出しごとに独立した送信チャネルが返されます。異なる行への変更を並行して行う場合に意図的に使用します。
  • イベントハンドラー内の useSubmit() — 自動保存、キーボードショートカット、onChange によるトリガーに適したプログラムによる送信方法です。
  • 送信中に fetcher.formData を読み取る — 意図された使い方であり、楽観的 UI の標準的なデータソースです。
  • 送信後も useActionData のデータが保持される — 既知の動作です。次のナビゲーションまたはアクションが発生するまで、最後のアクション結果を返します。
  • <Form> の navigate={false} — フェッチャーフォームに変換します。フェッチャーへの参照を保持しない <fetcher.Form> と同等です。
  • parseMultipartFormData / アップロードハンドラーの unstable_ プレフィックス — v2 では固定されています。「不安定な API」として指摘しないでください。

コンテキストに応じたルール

以下の条件を満たす場合に限り、指摘してください。

問題次の場合に限り指摘
<Form> ではなくネイティブの <form> を使用メソッドが POST で、ルートに action がある場合 — GET フォームと外部 URL のフォームは問題ありません
保留中の状態がないフォームが POST で、コンポーネント内のどこにも useNavigation() / fetcher.state の読み取りがない場合
作成後にアクションが json({ ok: true }) を返すルートが「/new」または作成画面の場合 — 同じページの編集フォームが JSON を返すのは問題ありません
method="put" / "patch" / "delete"その画面でプログレッシブエンハンスメントが対象となる場合(公開アプリ)— 管理用ツールや JS 専用ツールは、ドキュメントに記載があれば対象外にできます
上限のない unstable_createMemoryUploadHandlerアップロード対象がユーザー指定のファイルである場合(サイズが固定された内部アーティファクトではない場合)
ミューテーションごとに別々のルートがあるミューテーションが、互換性のある認証ルールを持つ同じリソースを操作する場合 — ルールの異なる関連リソースは問題ありません
formAction フィルターなしの useNavigation()誤検出を引き起こすほかのナビゲーション対象(サイドバーの <Link>、関連フォーム)がコンポーネントに含まれる場合
fetcher.formData を state にミラーリングその値がユーザーに表示される要素(ボタンのラベル、件数、トグル)を制御する場合 — ローカルな「編集中」フラグは該当しません

ハードゲート(指摘を書く前に実施)

以下を順番に実行してください。報告しようとしている一連の問題について、すべてのゲートを通過するまで、ユーザー向けの指摘を下書きしないでください。

  1. 場所の証拠 — 合格: 各問題に、リポジトリのパスと、読んだファイルから引用した行範囲または短い逐語引用を記載します(記憶や差分だけに基づく推測は不可)。ルートモジュール、コンポーネント、および存在する場合は action を明記します。

  2. 適用除外の確認 — 合格: 各問題について、有効なパターン(指摘しない)および該当するコンテキストに応じたルールの項目に該当しない理由を、1 行で説明できます。

  3. フォームメソッドの確認 — 合格: intent、encType、redirect、または保留中の状態の欠如を指摘する前に、そのフォームが method="post"(または put|patch|delete)であることを確認します。GET フォームは検索やフィルターに使用され、アクションではなくローダーを呼び出すため、POST フォームのルールを適用すると誤検出になります。

  4. プロトコル — 合格: このレビューについて、review-verification-protocol の事前報告検証チェックリストを完了しています。

追加ドキュメント

  • フォームと fetcher の誤用 — 手動の fetch()、ネイティブの <form>、誤ったプリミティブ: references/form-vs-fetcher.md
  • 保留状態のアンチパターン — useState フラグ、ページ全体と行単位の違い、状態の欠如: references/pending-state.md
  • アップロードと FormData の検証 — 上限のないハンドラー、encType の欠如、未検証のキー、ミラーリングされた楽観的状態: references/uploads-validation.md
  • 複数アクションのルート — intent パターンの違反、PE フォールバックのない PUT/DELETE、送信ボタンの欠如: references/multi-action-routes.md
  • 標準的なパターン — 関連する remix-v2-forms を参照してください。

リファレンスを読み込むタイミング

  • fetch() / axios / ネイティブの <form> を呼び出すフォーム、または <Form> と useFetcher のどちらを使うかを確認する場合 → form-vs-fetcher.md
  • 読み込みフラグ、スピナー、ボタンの無効化ロジック、行単位の保留状態を確認する場合 → pending-state.md
  • ファイルのアップロード、unstable_* ハンドラー、FormData の解析、楽観的 UI を確認する場合 → uploads-validation.md
  • 複数のミューテーション、intent フィールド、PUT/DELETE メソッドを含むルートを確認する場合 → multi-action-routes.md

レビューの確認事項

  1. アプリ内のすべての変更処理は、ルートの action を経由していますか(手動の fetch() はありませんか)?
  2. <Form> と useFetcher のどちらを使うかは、URLを変更するかどうかに基づいていますか?
  3. 保留中の状態は useNavigation() / fetcher.state から取得していますか(useState は使っていませんか)?
  4. 行ごとのスピナーは、ページ全体の useNavigation ではなく、行ごとの fetcher.state に接続されていますか?
  5. ファイルアップロードフォームでは encType="multipart/form-data" を設定し、上限のあるハンドラーを使用していますか?
  6. FormData の値は、DB に渡す前に検証されていますか?
  7. 1つのリソースに対する複数の変更処理には、別々のルートではなくインテントパターンを使用していますか?
  8. POST フォームには、プログレッシブエンハンスメントに対応する実際の送信ボタンが少なくとも1つありますか?

誤検出に関する注意事項

  • ルート以外のコンポーネント内に <Form> がレンダリングされていても、最も近いルートの action に紐づいています。「action がない」と指摘する前に、ルートファイルを確認してください。
  • 送信が成功した後に useActionData() がデータを返すのは想定された動作です。データは次のナビゲーションまで保持されます。成功バナーが閉じる手段なしに無条件で表示される場合に限り、指摘してください。
  • Form を別名でインポートしているコード(例:import { Form as RemixForm })も Remix コンポーネントです。ローカル名ではなく、インポート元に基づいて判定してください。

指摘事項を提出する前に

ハードゲート(特にゲート4)を完了してから、review-verification-protocol の報告前チェックを引き続き通過する問題のみを報告してください。

コメント