Динамические маршруты
Когда точные названия сегментов заранее неизвестны и требуется создавать маршруты из динамических данных, можно использовать Динамические сегменты, которые заполняются во время запроса или пререндерятся при сборке.
Соглашение
Динамический сегмент создается путем заключения имени папки в квадратные скобки: [folderName]
. Например, [id]
или [slug]
.
Динамические сегменты передаются как проп params
в функции layout
, page
, route
и generateMetadata
.
Пример
Например, блог может включать маршрут app/blog/[slug]/page.js
, где [slug]
— это динамический сегмент для постов.
export default function Page({ params }: { params: { slug: string } }) {
return <div>Мой пост: {params.slug}</div>
}
export default function Page({ params }) {
return <div>Мой пост: {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
, запросы автоматически мемоизируются. Это означает, что fetch
с одинаковыми аргументами в нескольких generateStaticParams
, Layouts и Pages выполнится только один раз, что сокращает время сборки.
Используйте руководство по миграции, если переходите с директории pages
.
Подробнее и расширенные сценарии использования см. в документации по функции generateStaticParams
.
Сегменты с перехватом всех путей (Catch-all)
Динамические сегменты можно расширить для перехвата всех последующих сегментов, добавив многоточие внутри скобок [...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
.
Разница между catch-all и опциональными catch-all сегментами в том, что опциональные соответствуют маршруту без параметра (/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>Моя страница</h1>
}
export default function Page({ params }) {
return <h1>Моя страница</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.