Динамические маршруты

Когда точные названия сегментов заранее неизвестны и нужно создавать маршруты из динамических данных, можно использовать динамические сегменты, которые заполняются во время запроса или пререндерятся во время сборки.

Соглашение

Динамический сегмент создаётся путём заключения имени папки в квадратные скобки: [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>
}
МаршрутПример URLparams
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.

Сегменты с перехватом всех параметров

Динамические сегменты можно расширить для перехвата всех последующих параметров, добавив многоточие внутри скобок [...folderName].

Например, app/shop/[...slug]/page.js будет соответствовать /shop/clothes, а также /shop/clothes/tops, /shop/clothes/tops/t-shirts и т.д.

МаршрутПример URLparams
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, в дополнение к /shop/clothes, /shop/clothes/tops, /shop/clothes/tops/t-shirts.

Разница между сегментами с перехватом всех и опциональными сегментами с перехватом всех в том, что опциональные соответствуют маршруту без параметра (/shop в примере выше).

МаршрутПример URLparams
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/[categoryId]/[itemId]/page.js{ categoryId: string, itemId: string }

Полезно знать: В будущем это может автоматически выполняться плагином TypeScript.