@react-router/fs-routes
パッケージは、ファイル規則に基づくルート設定を可能にします。
まず、@react-router/fs-routes
パッケージをインストールします。
npm i @react-router/fs-routes
次に、それを使用して、`app/routes.ts`ファイルでルート設定を提供します。
import { type RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export default flatRoutes() satisfies RouteConfig;
デフォルトでは、app/routes
ディレクトリ内のルートが検索されますが、これはアプリディレクトリからの相対パスである rootDirectory
オプションで設定できます。
import { type RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export default flatRoutes({
rootDirectory: "file-routes",
}) satisfies RouteConfig;
このガイドの残りの部分では、デフォルトの app/routes
ディレクトリを使用していることを前提としています。
app/routes
ディレクトリ内のモジュールはすべて、アプリケーションのルートになります。ファイル名は、ルートの URL パス名に対応します。ただし、_index.tsx
は例外で、ルートルートのインデックスルートとなります。.js
、.jsx
、.ts
、または .tsx
のファイル拡張子を使用できます。
app/
├── routes/
│ ├── _index.tsx
│ └── about.tsx
└── root.tsx
URL | 一致するルート |
---|---|
/ |
app/routes/_index.tsx |
/about |
app/routes/about.tsx |
ネストされたルーティングのため、これらのルートは app/root.tsx
のアウトレットにレンダリングされます。
ルートファイル名に .
を追加すると、URL に /
が作成されます。
app/
├── routes/
│ ├── _index.tsx
│ ├── about.tsx
│ ├── concerts.trending.tsx
│ ├── concerts.salt-lake-city.tsx
│ └── concerts.san-diego.tsx
└── root.tsx
URL | 一致するルート |
---|---|
/ |
app/routes/_index.tsx |
/about |
app/routes/about.tsx |
/concerts/trending |
app/routes/concerts.trending.tsx |
/concerts/salt-lake-city |
app/routes/concerts.salt-lake-city.tsx |
/concerts/san-diego |
app/routes/concerts.san-diego.tsx |
ドット区切り文字はネストも作成します。詳細はネストのセクションを参照してください。
通常、URL は静的ではなく、データ駆動型です。動的セグメントを使用すると、URL のセグメントを一致させ、その値をコードで使用できます。$
プレフィックスを使用して作成します。
app/
├── routes/
│ ├── _index.tsx
│ ├── about.tsx
│ ├── concerts.$city.tsx
│ └── concerts.trending.tsx
└── root.tsx
URL | 一致するルート |
---|---|
/ |
app/routes/_index.tsx |
/about |
app/routes/about.tsx |
/concerts/trending |
app/routes/concerts.trending.tsx |
/concerts/salt-lake-city |
app/routes/concerts.$city.tsx |
/concerts/san-diego |
app/routes/concerts.$city.tsx |
値は URL から解析され、さまざまな API に渡されます。これらの値を「URL パラメータ」と呼びます。URL パラメータにアクセスするのに最も便利な場所は、ローダーとアクションです。
export async function serverLoader({ params }) {
return fakeDb.getAllConcertsForCity(params.city);
}
params
オブジェクトのプロパティ名は、ファイルの名前 ($city.tsx
は params.city
になる) に直接対応していることに注意してください。
ルートには、concerts.$city.$date
のように、複数の動的セグメントを含めることができます。どちらも params オブジェクトで名前によってアクセスされます。
export async function serverLoader({ params }) {
return fake.db.getConcerts({
date: params.date,
city: params.city,
});
}
詳細は、ルーティングガイドを参照してください。
ネストされたルーティングとは、URL のセグメントをコンポーネント階層とデータに結合するという一般的な考え方です。ルーティングガイドで詳細を読むことができます。
ドット区切り文字を使用してネストされたルートを作成します。.
の前のファイル名が別のルートファイル名と一致する場合、自動的に一致する親のルートの子ルートになります。これらのルートを検討してください。
app/
├── routes/
│ ├── _index.tsx
│ ├── about.tsx
│ ├── concerts._index.tsx
│ ├── concerts.$city.tsx
│ ├── concerts.trending.tsx
│ └── concerts.tsx
└── root.tsx
app/routes/concerts.
で始まるすべてのルートは、app/routes/concerts.tsx
の子ルートとなり、親ルートのアウトレット内にレンダリングされます。
URL | 一致するルート | レイアウト |
---|---|---|
/ |
app/routes/_index.tsx |
app/root.tsx |
/about |
app/routes/about.tsx |
app/root.tsx |
/concerts |
app/routes/concerts._index.tsx |
app/routes/concerts.tsx |
/concerts/trending |
app/routes/concerts.trending.tsx |
app/routes/concerts.tsx |
/concerts/salt-lake-city |
app/routes/concerts.$city.tsx |
app/routes/concerts.tsx |
ユーザーが親 URL を直接訪れたときに親のアウトレット内に何かがレンダリングされるように、ネストされたルートを追加するときには、通常、インデックスルートを追加することをお勧めします。
たとえば、URL が /concerts/salt-lake-city
の場合、UI 階層は次のようになります。
<Root>
<Concerts>
<City />
</Concerts>
</Root>
URL をネストしたいが、自動レイアウトネストは望まない場合があります。親セグメントにアンダースコアを付けることで、ネストをオプトアウトできます。
app/
├── routes/
│ ├── _index.tsx
│ ├── about.tsx
│ ├── concerts.$city.tsx
│ ├── concerts.trending.tsx
│ ├── concerts.tsx
│ └── concerts_.mine.tsx
└── root.tsx
URL | 一致するルート | レイアウト |
---|---|---|
/ |
app/routes/_index.tsx |
app/root.tsx |
/about |
app/routes/about.tsx |
app/root.tsx |
/concerts/mine |
app/routes/concerts_.mine.tsx |
app/root.tsx |
/concerts/trending |
app/routes/concerts.trending.tsx |
app/routes/concerts.tsx |
/concerts/salt-lake-city |
app/routes/concerts.$city.tsx |
app/routes/concerts.tsx |
/concerts/mine
は app/routes/concerts.tsx
ではなく、app/root.tsx
とネストすることに注意してください。`trailing_` アンダースコアはパスセグメントを作成しますが、レイアウトネストは作成しません。
`trailing_` アンダースコアは、親の署名の最後に長いビットがあり、あなたを遺言から除外し、後に続くセグメントをレイアウトネストから削除するようなものと考えてください。
これをパスレスルートと呼びます。
URL にパスセグメントを追加せずに、レイアウトをルートのグループと共有したい場合があります。一般的な例として、公開ページやログインしたアプリエクスペリエンスとは異なるヘッダー/フッターを持つ認証ルートのセットがあります。これは `_leading` アンダースコアを使用して行うことができます。
app/
├── routes/
│ ├── _auth.login.tsx
│ ├── _auth.register.tsx
│ ├── _auth.tsx
│ ├── _index.tsx
│ ├── concerts.$city.tsx
│ └── concerts.tsx
└── root.tsx
URL | 一致するルート | レイアウト |
---|---|---|
/ |
app/routes/_index.tsx |
app/root.tsx |
/login |
app/routes/_auth.login.tsx |
app/routes/_auth.tsx |
/register |
app/routes/_auth.register.tsx |
app/routes/_auth.tsx |
/concerts |
app/routes/concerts.tsx |
app/routes/concerts.tsx |
/concerts/salt-lake-city |
app/routes/concerts.$city.tsx |
app/routes/concerts.tsx |
`_leading` アンダースコアは、ファイル名の上にブランケットを引いて、URL からファイル名を隠していると考えてください。
ルートセグメントを括弧で囲むと、セグメントがオプションになります。
app/
├── routes/
│ ├── ($lang)._index.tsx
│ ├── ($lang).$productId.tsx
│ └── ($lang).categories.tsx
└── root.tsx
URL | 一致するルート |
---|---|
/ |
app/routes/($lang)._index.tsx |
/categories |
app/routes/($lang).categories.tsx |
/en/categories |
app/routes/($lang).categories.tsx |
/fr/categories |
app/routes/($lang).categories.tsx |
/american-flag-speedo |
app/routes/($lang)._index.tsx |
/en/american-flag-speedo |
app/routes/($lang).$productId.tsx |
/fr/american-flag-speedo |
app/routes/($lang).$productId.tsx |
なぜ/american-flag-speedo
が ($lang).$productId.tsx
ルートではなく ($lang)._index.tsx
ルートに一致するのか疑問に思うかもしれません。これは、オプションの動的パラメータセグメントの後に別の動的パラメータが続く場合、/american-flag-speedo
のような単一セグメントの URL が /:lang
/:productId
に一致する必要があるかどうかを確実に判断できないためです。オプションのセグメントは積極的に一致するため、/:lang
に一致します。このタイプのセットアップがある場合は、($lang)._index.tsx
ローダーで params.lang
を確認し、params.lang
が有効な言語コードでない場合は、現在/デフォルトの言語の /:lang/american-flag-speedo
にリダイレクトすることをお勧めします。
動的セグメントは単一のパスセグメント (URL 内の 2 つの /
の間の部分) に一致するのに対し、スプラットルートはスラッシュを含む URL の残りの部分に一致します。
app/
├── routes/
│ ├── _index.tsx
│ ├── $.tsx
│ ├── about.tsx
│ └── files.$.tsx
└── root.tsx
URL | 一致するルート |
---|---|
/ |
app/routes/_index.tsx |
/about |
app/routes/about.tsx |
/beef/and/cheese |
app/routes/$.tsx |
/files |
app/routes/files.$.tsx |
/files/talks/react-conf_old.pdf |
app/routes/files.$.tsx |
/files/talks/react-conf_final.pdf |
app/routes/files.$.tsx |
/files/talks/react-conf-FINAL-MAY_2024.pdf |
app/routes/files.$.tsx |
動的ルートパラメータと同様に、スプラットルートの params
で "*"
キーを使用して、一致したパスの値にアクセスできます。
export async function serverLoader({ params }) {
const filePath = params["*"];
return fake.getFileInfo(filePath);
}
これらのルート規則に使用される特殊文字の 1 つを実際に URL の一部にしたい場合は、[]
文字を使用して規則をエスケープできます。これは、URL に拡張子を含むリソースルートに特に役立ちます。
ファイル名 | URL |
---|---|
app/routes/sitemap[.]xml.tsx |
/sitemap.xml |
app/routes/[sitemap.xml].tsx |
/sitemap.xml |
app/routes/weird-url.[_index].tsx |
/weird-url/_index |
app/routes/dolla-bills-[$].tsx |
/dolla-bills-$ |
app/routes/[[so-weird]].tsx |
/[so-weird] |
`app/routes/reports.$id[.pdf].ts | `/reports/123.pdf |
ルートは、ルートモジュールを定義する route.tsx
ファイルを含むフォルダにすることもできます。フォルダ内の残りのファイルはルートになりません。これにより、他のフォルダで機能名を繰り返す代わりに、コードをルートの近くに整理できます。
フォルダ内のファイルはルートパスには意味がなく、ルートパスはフォルダ名によって完全に定義されます。
これらのルートを検討してください。
app/
├── routes/
│ ├── _landing._index.tsx
│ ├── _landing.about.tsx
│ ├── _landing.tsx
│ ├── app._index.tsx
│ ├── app.projects.tsx
│ ├── app.tsx
│ └── app_.projects.$id.roadmap.tsx
└── root.tsx
一部またはすべてが、独自の `route` モジュールを保持するフォルダにすることができます。
app/
├── routes/
│ ├── _landing._index/
│ │ ├── route.tsx
│ │ └── scroll-experience.tsx
│ ├── _landing.about/
│ │ ├── employee-profile-card.tsx
│ │ ├── get-employee-data.server.ts
│ │ ├── route.tsx
│ │ └── team-photo.jpg
│ ├── _landing/
│ │ ├── footer.tsx
│ │ ├── header.tsx
│ │ └── route.tsx
│ ├── app._index/
│ │ ├── route.tsx
│ │ └── stats.tsx
│ ├── app.projects/
│ │ ├── get-projects.server.ts
│ │ ├── project-buttons.tsx
│ │ ├── project-card.tsx
│ │ └── route.tsx
│ ├── app/
│ │ ├── footer.tsx
│ │ ├── primary-nav.tsx
│ │ └── route.tsx
│ ├── app_.projects.$id.roadmap/
│ │ ├── chart.tsx
│ │ ├── route.tsx
│ │ └── update-timeline.server.ts
│ └── contact-us.tsx
└── root.tsx
ルートモジュールをフォルダに変換すると、ルートモジュールは `folder/route.tsx` になり、フォルダ内の他のすべてのモジュールはルートにならないことに注意してください。例えば
# these are the same route:
app/routes/app.tsx
app/routes/app/route.tsx
# as are these
app/routes/app._index.tsx
app/routes/app._index/route.tsx