Dynamic Routes
具体的なセグメント名を事前に知らない場合や、Dynamic データから routes を作成したい場合は、request 時に詰め込むか、もしくは prerendered を build 時に使用できる dynamic セグメントを使用できます。
Convention
Dynamic セグメントは、フォルダー名を角括弧で囲むことで作成できます:[folderName]
。たとえば、[id]
または[slug]
。
Dynamic セグメントは、params
プロップとして layout
、page
、route
、および generateMetadata
関数に渡されます。
Example
例えば、ブログは次の route app/blog/[slug]/page.js
を含むことができます。ここで [slug]
はブログ投稿のための Dynamic セグメントです。
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>
}
Route | 例 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' } |
セグメントの params を生成する方法を学びたい方は、generateStaticparams() ページをご覧ください。
Good to know: Dynamic セグメントは
pages
ディレクトリの Dynamic Routes と同等です。
Generating Static Params
generateStaticParams
関数は dynamic route セグメントと組み合わせて使用することで、request 時ではなく、build 時に routes を 静的に生成することができます。
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
関数の主な利点は、データのスマート取得です。もしコンテンツが fetch
request を用いて generateStaticParams
関数内で取得された場合、そのリクエストは自動的に保持されます。これは、複数の generateStaticParams
、layout、ページ間で同じ引数の fetch
request が一度だけ行われることを意味します。これにより、 build 時間が短縮されます。
あなたが pages
ディレクトリから移行しているなら、移行ガイドを使用してください。
詳細な情報や高度な使用例については、generateStaticParams
server function documentation をご覧ください。
Catch-all Segments
Dynamic セグメントは、ブラケット内に省略記号 [...folderName]
を追加することで、後続のすべてのcatch-allセグメントを拡張できます。
例えば、app/shop/[...slug]/page.js
は /shop/clothes
と一致しますが、/shop/clothes/tops
、/shop/clothes/tops/t-shirts
なども一致します。
Route | 例 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'] } |
Optional Catch-all Segments
Catch-all セグメントは、二重の角括弧にパラメーターを含めることで任意にすることができます:[[...folderName]]
。
たとえば、app/shop/[[...slug]]/page.js
は /shop
にも一致します。それは /shop/clothes
、/shop/clothes/tops
、/shop/clothes/tops/t-shirts
に加えてです。
catch-allとオプショナル catch-allセグメントの違いは、オプショナルを用いると、パラメーターのない route もマッチします(上記の例では/shop
)。
Route | 例 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 を使用するとき、設定された route セグメントに応じてparams
に型を追加することができます。
export default function Page({ params }: { params: { slug: string } }) {
return <h1>My Page</h1>
}
export default function Page({ params }) {
return <h1>My Page</h1>
}
Route | params Type 定義 |
---|---|
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 } |
Good to know: これは将来的には TypeScript plugin によって自動的に行われるかもしれません。