React Route v7触ってみる

基本的には以下を参照する

プロジェクトの構築
bunx create-react-router@latest

ルーティング
ルートの設定
ルートは app/routes.ts で設定します。各ルートには、URL に一致させるための URL パターンと、その動作を定義するルートモジュールへのファイルパスという、2 つの必須部分があります。
app/routes.tsimport { type RouteConfig, route, } from "@react-router/dev/routes"; export default [ route("some/path", "./some/file.tsx"), // pattern ^ ^ モジュールファイル ] satisfies RouteConfig;
とドキュメントには書いてあるけど構築されたプロジェクトのコード見てみると以下のようになってる
import { type RouteConfig, index } from "@react-router/dev/routes";
export default [index("routes/home.tsx")] satisfies RouteConfig;
route
の第一引数が/
、つまりインデックスルートのときのヘルパー的な感じでindex
が用意されてるだけっぽい

ルートをネストする
import { type RouteConfig, index, route } from "@react-router/dev/routes";
export default [
index("routes/home.tsx"),
route("dashboard", "routes/dashboard.tsx", [
// 子ルート
index("routes/dashboard/home.tsx"),
route("settings", "routes/dashboard/settings.tsx"),
]),
] satisfies RouteConfig;
モジュールファイルの追加
import type { FC } from "react";
import { Outlet } from "react-router";
const Dashboard: FC = () => {
return (
<div className="flex h-screen items-center justify-center gap-4 text-2xl">
dashboard
<span>/</span>
<Outlet />
</div>
);
};
export default Dashboard;
import type { FC } from "react";
const DashboardHome: FC = () => {
return <div>home</div>;
};
export default DashboardHome;
import type { FC } from "react";
const DashboardSettings: FC = () => {
return <div>settings</div>;
};
export default DashboardSettings;
/dashboard |
/dashboard/settings |
---|---|
![]() |
![]() |

ファイルベースルーティング
設定ではなく、ファイル命名規則でルートを定義したい場合は、
@react-router/fs-routes
パッケージで ファイルシステムルーティング規則 が提供されます。必要に応じて、さまざまなルーティング規則を組み合わせることもできます。app/routes.tsimport { type RouteConfig, route, } from "@react-router/dev/routes"; import { flatRoutes } from "@react-router/fs-routes"; export default [ route("/", "./home.tsx"), ...(await flatRoutes()), ] satisfies RouteConfig;
とあるけどflatRoutes
使うならapp/routes/_index.tsx
が必須っぽい...?
命名規則でこれがルートルートになる、と思うから以下のようにすればいいのでは...?
その場合↑の例のroute("/", "./home.tsx")
はなんなんだろう
import type { RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export default [...(await flatRoutes())] satisfies RouteConfig;
flatRoutes
の規則に載ってこないようなルートを手動で追加することもできる
import { type RouteConfig, route } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export default [
route("/test", "./test.tsx"),
...(await flatRoutes()),
] satisfies RouteConfig;

レイアウトルート
layout
を使用すると、レイアウトルートは子に対して新しいネストを作成しますが、URL にセグメントを追加しません。ルートルートに似ていますが、任意のレベルで追加できます。app/routes.tsimport { type RouteConfig, index, layout, prefix, route, } 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構造には影響を与えない

ルートプレフィックス
prefix
を使用すると、親ルートファイルを導入せずに、ルートのセットにパスプレフィックスを追加できます。app/routes.tsimport { type RouteConfig, index, layout, prefix, route, } 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;
こっちはlayout
とは逆でネストは作らないけどURL構造的なprefix
を付与したグループを作れる

動的セグメント
パスセグメントが : で始まる場合、それは「動的セグメント」になります。ルートが URL と一致すると、動的セグメントは URL から解析され、他のルーター API に params として提供されます。
app/routes.tsroute("teams/:teamId", "./team.tsx"),
app/team.tsximport type { Route } from "./+types/team"; export async function loader({ params }: Route.LoaderArgs) { // ^? { teamId: string } } export default function Component({ params, }: Route.ComponentProps) { params.teamId; // ^ string }
試しにコンポーネントでprops
から取得してみた
ファイルベースルーティングの場合はteams.$teamId.tsx
みたいな感じ?

オプションのセグメント
セグメントの最後に ? を追加すると、ルートセグメントをオプションにすることができます。
app/routes.tsroute(":lang?/categories", "./categories.tsx"),
オプションの静的セグメントを含めることもできます。
app/routes.tsroute("users/:userId/edit?", "./user.tsx");
たしかにオプショナルにすると他のルーター API から params
を参照したときにstring | undefined
のようなユニオンになっている

スプラット
「キャッチオール」および「スター」セグメントとも呼ばれます。ルートパスパターンが /* で終わる場合、他の / 文字を含む、/ に続く任意の文字に一致します。
route("files/*", "./files.tsx"),
import type { FC } from "react";
import type { Route } from "./+types/files";
const Files: FC<Route.ComponentProps> = ({ params }) => {
// params["*"] には、files/ の後の残りの URL が含まれます
const { "*": splat } = params;
return (
<div className="flex h-screen items-center justify-center text-2xl">
project {splat}
</div>
);
};
export default Files;
params["*"]
の型的にはstring
になるみたい