ダイナミックルート
事前に正確なセグメント名がわからず、動的なデータからルートを作成したい場合、リクエスト時に動的に生成されるか、ビルド時にプリレンダリングされるダイナミックセグメントを使用できます。
規約
ダイナミックセグメントは、フォルダ名を角括弧で囲むことで作成できます: [folderName]
。例えば、[id]
や [slug]
などです。
ダイナミックセグメントは layout
、page
、route
、generateMetadata
関数に params
プロップとして渡されます。
例
例えば、ブログでは app/blog/[slug]/page.js
というルートを含めることができ、[slug]
はブログ投稿のダイナミックセグメントです。
export default function Page({ params }: { params: { slug: string } }) {
return <div>My Post: {params.slug}</div>
}
export default function Page({ params }) {
return <div>My Post: {params.slug}</div>
}
ルート | 例のURL | params |
---|---|---|
app/blog/[slug]/page.js | /blog/a | { slug: 'a' } |
app/blog/[slug]/page.js | /blog/b | { slug: 'b' } |
app/blog/[slug]/page.js | /blog/c | { slug: 'c' } |
セグメントのパラメータを生成する方法については、generateStaticParams() ページを参照してください。
豆知識: ダイナミックセグメントは
pages
ディレクトリのダイナミックルートと同等です。
静的パラメータの生成
generateStaticParams
関数はダイナミックルートセグメントと組み合わせて使用でき、リクエスト時にオンデマンドで生成する代わりにビルド時にルートを静的生成できます。
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
generateStaticParams
関数の主な利点は、データのスマートな取得です。generateStaticParams
関数内で fetch
リクエストを使用してコンテンツを取得する場合、リクエストは自動的にメモ化されます。つまり、複数の generateStaticParams
、レイアウト、ページ間で同じ引数を持つ fetch
リクエストは一度だけ行われ、ビルド時間が短縮されます。
pages
ディレクトリから移行する場合は、移行ガイドを参照してください。
詳細な情報と高度な使用例については、generateStaticParams
サーバー関数ドキュメントを参照してください。
キャッチオールセグメント
ダイナミックセグメントは、括弧内に省略記号を追加することで、後続のセグメントをキャッチオールするように拡張できます [...folderName]
。
例えば、app/shop/[...slug]/page.js
は /shop/clothes
だけでなく、/shop/clothes/tops
、/shop/clothes/tops/t-shirts
などにもマッチします。
ルート | 例のURL | params |
---|---|---|
app/shop/[...slug]/page.js | /shop/a | { slug: ['a'] } |
app/shop/[...slug]/page.js | /shop/a/b | { slug: ['a', 'b'] } |
app/shop/[...slug]/page.js | /shop/a/b/c | { slug: ['a', 'b', 'c'] } |
オプショナルキャッチオールセグメント
キャッチオールセグメントは、パラメータを二重角括弧で囲むことでオプショナルにできます: [[...folderName]]
。
例えば、app/shop/[[...slug]]/page.js
は /shop/clothes
、/shop/clothes/tops
、/shop/clothes/tops/t-shirts
に加えて、/shop
にもマッチします。
キャッチオールとオプショナルキャッチオールセグメントの違いは、オプショナルの場合、パラメータなしのルート(上記の例では /shop
)にもマッチすることです。
ルート | 例のURL | params |
---|---|---|
app/shop/[[...slug]]/page.js | /shop | {} |
app/shop/[[...slug]]/page.js | /shop/a | { slug: ['a'] } |
app/shop/[[...slug]]/page.js | /shop/a/b | { slug: ['a', 'b'] } |
app/shop/[[...slug]]/page.js | /shop/a/b/c | { slug: ['a', 'b', 'c'] } |
TypeScript
TypeScript を使用する場合、設定されたルートセグメントに応じて params
の型を追加できます。
export default function Page({ params }: { params: { slug: string } }) {
return <h1>My Page</h1>
}
export default function Page({ params }) {
return <h1>My Page</h1>
}
ルート | params 型定義 |
---|---|
app/blog/[slug]/page.js | { slug: string } |
app/shop/[...slug]/page.js | { slug: string[] } |
app/shop/[[...slug]]/page.js | { slug?: string[] } |
app/[categoryId]/[itemId]/page.js | { categoryId: string, itemId: string } |
豆知識: これは将来的に TypeScript プラグイン によって自動的に行われる可能性があります。