skills/react-router-loader/SKILL.md
React Router v7 の loader パターンのリファレンス。画面表示に伴うデータフェッチに loader を使うことでデータの流れを一方向にし、コードの見通しを良くし、不要な useEffect の利用を抑制する。
npx skillsauth add myuon/agent-skills react-router-loaderInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
画面表示に伴うデータフェッチには loader パターンを使う。データの流れを一方向(loader → コンポーネント)にすることで、コードの見通しが良くなり、不要な useEffect を排除できる。
React Router v7 には 3 つのモードがあり、loader の書き方が異なる。
| 判別ポイント | Framework Mode | Data Mode | Declarative Mode |
|---|---|---|---|
| vite.config.ts に reactRouter() プラグイン | ✅ | — | — |
| createBrowserRouter を使用 | — | ✅ | — |
| <BrowserRouter> を使用 | — | — | ✅ |
Declarative Mode では loader は使えない。
createBrowserRouter を使うモード。Vite プラグイン不要。
import {
createBrowserRouter,
RouterProvider,
useLoaderData,
} from "react-router";
interface User {
id: string;
name: string;
}
const router = createBrowserRouter([
{
path: "/users/:id",
Component: UserPage,
loader: async ({ params }): Promise<User> => {
const res = await fetch(`/api/users/${params.id}`);
if (!res.ok) throw new Response("Not Found", { status: 404 });
return res.json();
},
},
]);
function UserPage() {
const user = useLoaderData<User>();
return <div>{user.name}</div>;
}
// エントリポイント
ReactDOM.createRoot(root).render(<RouterProvider router={router} />);
@react-router/dev の Vite プラグインを使うモード。ファイルベースルーティング・型安全な loader。
./+types/ ディレクトリに自動生成される型を使うことで、loader の戻り値がコンポーネントの props に型安全に渡される。
// app/routes/users.tsx
import type { Route } from "./+types/users";
// Route.LoaderArgs で params, request の型が付く
export async function loader({ params, request }: Route.LoaderArgs) {
const user = await db.user.findUnique({ where: { id: params.id } });
if (!user) {
throw new Response("Not Found", { status: 404 });
}
return { user };
}
// Route.ComponentProps により loaderData の型が loader の戻り値から自動推論される
export default function Users({ loaderData }: Route.ComponentProps) {
const { user } = loaderData;
return <div>{user.name}</div>;
}
loader で throw した Response は ErrorBoundary でキャッチされる。
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
if (isRouteErrorResponse(error)) {
return <div>{error.status}: {error.data}</div>;
}
return <div>Unexpected error</div>;
}
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
const q = url.searchParams.get("q"); // クエリパラメータ
const cookie = request.headers.get("Cookie"); // ヘッダー
return { results: await search(q) };
}
development
React の useEffect を避け、より適切なパターンに置き換えるためのガイド。useEffect を含むコードを書こうとしているとき、またはコードレビューで useEffect を検出したとき、代替パターンを提案するために使う。
development
LLM Key Ring (lkr) - macOS Keychainを使ったAPIキー管理ツールのリファレンス。APIキーの登録・取得・一覧・環境変数注入が必要なときに使う。
tools
GitHub CLI (gh) で Issue・Sub-issue・PR・CI を操作するためのクイックリファレンス
tools
ユーザーがタスク一覧に対して実装を求めてきた際に参照するスキル。複数のイシューを同時に取り組むためのワークフロー。