ルーティング

ルートの設定

ルートは app/routes.ts で設定します。各ルートには、URL をマッチさせるための URL パターンと、その動作を定義するルートモジュールへのファイルパスという、2 つの必須部分があります。

app/routes.ts
import {
  type RouteConfig,
  route,
} from "@react-router/dev/routes";
 
export default [
  route("some/path", "./some/file.tsx"),
  // パターン ^           ^ モジュールファイル
] satisfies RouteConfig;

以下は、より大きなルート設定のサンプルです。

app/routes.ts
import {
  type RouteConfig,
  route,
  index,
  layout,
  prefix,
} from "@react-router/dev/routes";
 
export default [
  index("./home.tsx"),
  route("about", "./about.tsx"),
 
  layout("./auth/layout.tsx", [
    route("login", "./auth/login.tsx"),
    route("register", "./auth/register.tsx"),
  ]),
 
  ...prefix("concerts", [
    index("./concerts/home.tsx"),
    route(":city", "./concerts/city.tsx"),
    route("trending", "./concerts/trending.tsx"),
  ]),
] satisfies RouteConfig;

設定ではなくファイル命名規則でルートを定義したい場合は、@react-router/fs-routes パッケージが ファイルシステムルーティング規則 を提供します。必要に応じて、異なるルーティング規則を組み合わせることもできます。

app/routes.ts
import { type RouteConfig, route } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
 
export default = [
  route("/", "./home.tsx"),
 
  ...await flatRoutes(),
] satisfies RouteConfig;

ルートモジュール

routes.ts で参照されるファイルは、各ルートの動作を定義します。

app/routes.ts
route("teams/:teamId", "./team.tsx"),
//           ルートモジュール ^^^^^^^^

以下は、ルートモジュールのサンプルです。

app/team.tsx
// 型安全性/推論を提供
import type { Route } from "./+types/team";
 
// コンポーネントに `loaderData` を提供
export async function loader({ params }: Route.LoaderArgs) {
  let team = await fetchTeam(params.teamId);
  return { name: team.name };
}
 
// ローダーが完了した後にレンダリング
export default function Component({
  loaderData,
}: Route.ComponentProps) {
  return <h1>{loaderData.name}</h1>;
}

ルートモジュールには、アクション、ヘッダー、エラー境界などの機能がありますが、これらについては次のガイド ルートモジュール で説明します。

ネストされたルート

ルートは、親ルートの中にネストできます。

app/routes.ts
import {
  type RouteConfig,
  route,
  index,
} from "@react-router/dev/routes";
 
export default [
  // 親ルート
  route("dashboard", "./dashboard.tsx", [
    // 子ルート
    index("./home.tsx"),
    route("settings", "./settings.tsx"),
  ]),
] satisfies RouteConfig;

親のパスは自動的に子に含まれるため、この設定では "/dashboard""/dashboard/settings" の両方の URL が作成されます。

子ルートは、親ルートの <Outlet/> を通してレンダリングされます。

app/dashboard.tsx
import { Outlet } from "react-router";
 
export default function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      {/* home.tsx または settings.tsx のいずれかになる */}
      <Outlet />
    </div>
  );
}

ルートルート

routes.ts のすべてのルートは、特別な app/root.tsx モジュールの中にネストされています。

レイアウトルート

layout を使用すると、レイアウトルートは子に対して新しいネストを作成しますが、URL にセグメントを追加しません。ルートルートのようなものですが、任意のレベルで追加できます。

app/routes.ts
import {
  type RouteConfig,
  route,
  layout,
  index,
  prefix,
} from "@react-router/dev/routes";
 
export default [
  layout("./marketing/layout.tsx", [
    index("./marketing/home.tsx"),
    route("contact", "./marketing/contact.tsx"),
  ]),
  ...prefix("projects", [
    index("./projects/home.tsx"),
    layout("./projects/project-layout.tsx", [
      route(":pid", "./projects/project.tsx"),
      route(":pid/edit", "./projects/edit-project.tsx"),
    ]),
  ]),
] satisfies RouteConfig;

projects/home.tsx をレイアウトに表示するには、アウトレットが必要です。

./projects/project-layout.tsx
import { Outlet } from "react-router";
 
export default function ProjectLayout() {
  return (
    <div>
      <aside>Example sidebar</aside>
      <main>
        <Outlet />
      </main>
    </div>
  );
}

インデックスルート

index(componentFile),

インデックスルートは、親の URL で親の Outlet にレンダリングされます(デフォルトの子ルートのように)。

app/routes.ts
import {
  type RouteConfig,
  route,
  index,
} from "@react-router/dev/routes";
 
export default [
  // / で root.tsx Outlet にレンダリング
  index("./home.tsx"),
  route("dashboard", "./dashboard.tsx", [
    // /dashboard で dashboard.tsx Outlet にレンダリング
    index("./dashboard-home.tsx"),
    route("settings", "./dashboard-settings.tsx"),
  ]),
] satisfies RouteConfig;

インデックスルートには子を持たせることができないことに注意してください。

ルートプレフィックス

prefix を使用すると、親ルートファイルを作成する必要なく、ルートのセットにパスプレフィックスを追加できます。

app/routes.ts
import {
  type RouteConfig,
  route,
  layout,
  index,
  prefix,
} from "@react-router/dev/routes";
 
export default [
  layout("./marketing/layout.tsx", [
    index("./marketing/home.tsx"),
    route("contact", "./marketing/contact.tsx"),
  ]),
  ...prefix("projects", [
    index("./projects/home.tsx"),
    layout("./projects/project-layout.tsx", [
      route(":pid", "./projects/project.tsx"),
      route(":pid/edit", "./projects/edit-project.tsx"),
    ]),
  ]),
] satisfies RouteConfig;

動的セグメント

パスセグメントが : で始まる場合、それは「動的セグメント」になります。ルートが URL に一致すると、動的セグメントは URL から解析され、他のルーター API に params として提供されます。

app/routes.ts
route("teams/:teamId", "./team.tsx"),
app/team.tsx
import type { Route } from "./+types/team";
 
export async function loader({ params }: Route.LoaderArgs) {
  //                           ^? { teamId: string }
}
 
export default function Component({
  params,
}: Route.ComponentProps) {
  params.teamId;
  //        ^ string
}

1 つのルートパスに複数の動的セグメントを含めることができます。

app/routes.ts
route("c/:categoryId/p/:productId", "./product.tsx"),
app/product.tsx
import type { Route } from "./+types/product";
 
async function loader({ params }: LoaderArgs) {
  //                    ^? { categoryId: string; productId: string }
}

特定のパス内のすべての動的セグメントが一意であることを確認する必要があります。そうしないと、params オブジェクトが設定されるにつれて、後の動的セグメントの値が以前の値を上書きします。

オプションセグメント

セグメントの末尾に ? を追加することで、ルートセグメントをオプションにすることができます。

app/routes.ts
route(":lang?/categories", "./categories.tsx"),

オプションの静的セグメントも使用できます。

app/routes.ts
route("users/:userId/edit?", "./user.tsx");

スプラット

「キャッチオール」または「スター」セグメントとも呼ばれます。ルートパスパターンが /* で終わる場合、他の / 文字を含む、/ に続く任意の文字に一致します。

app/routes.ts
route("files/*", "./files.tsx"),
app/files.tsx
export async function loader({ params }: Route.LoaderArgs) {
  // params["*"] には files/ の後の残りの URL が含まれます
}

* を分割代入できますが、新しい名前を割り当てる必要があります。一般的な名前は splat です。

const { "*": splat } = params;

コンポーネントルート

コンポーネントツリー内の任意の場所で、URL に一致するコンポーネントを使用することもできます。

import { Routes, Route } from "react-router";
 
function Wizard() {
  return (
    <div>
      <h1>Some Wizard with Steps</h1>
      <Routes>
        <Route index element={<StepOne />} />
        <Route path="step-2" element={<StepTwo />} />
        <Route path="step-3" element={<StepThree />} />
      </Routes>
    </div>
  );
}

これらのルートは、データローディング、アクション、コード分割、その他のルートモジュール機能には関与しないため、そのユースケースはルートモジュールのユースケースよりも限定的であることに注意してください。


次へ: ルートモジュール