Capítulo 113 de 456
Dynamic Segments capturam um valor da URL para gerar rotas a partir de dado dinâmico, quando o valor do segmento não é conhecido de antemão. Criados envolvendo o nome da pasta em colchetes ([folderName]); o valor capturado chega via prop params (Promise) em layout, page, route e generateMetadata.
[folderName]: segmento dinâmico simples, captura um valor ({ slug: 'a' }).[...folderName]: catch-all, captura múltiplos segmentos como array ({ slug: ['a','b'] }); não casa com a rota base sem sufixo.[[...folderName]]: optional catch-all, também casa com a rota sem sufixo ({ slug: undefined }).next/root-params.params é Promise: requer await ou use() (React) para acessar; em Client Components use use(params) ou o hook useParams().PageProps<'/route'>, LayoutProps<'/route'> ou RouteContext<'/route'> para tipar params; valores são sempre string, string[] ou undefined.generateStaticParams, params são dado runtime e precisam de <Suspense>; com generateStaticParams, o build valida e prerenderiza as amostras, e branches condicionais não cobertos pelas amostras só são validados na primeira request real.export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
return <div>My Post: {slug}</div>
}
await params.import { notFound } from 'next/navigation'
import type { Locale } from '@i18n/types'
import { isValidLocale } from '@i18n/utils'
function assertValidLocale(value: string): asserts value is Locale {
if (!isValidLocale(value)) notFound()
}
export default async function Page(props: PageProps<'/[locale]'>) {
const { locale } = await props.params // locale is typed as string
assertValidLocale(locale)
// locale is now typed as Locale
}
string para Locale via type guard + notFound().export async function generateStaticParams() {
return [{ slug: '1' }, { slug: '2' }, { slug: '3' }]
}
export default async function Page({ params }: PageProps<'/blog/[slug]'>) {
const { slug } = await params
return <Content slug={slug} />
}
generateStaticParams com amostras conhecidas em build time.| Route | Example URL | params |
|---|---|---|
app/blog/[slug]/page.js | /blog/a | { slug: 'a' } |
app/shop/[...slug]/page.js | /shop/a/b | { slug: ['a', 'b'] } |
app/shop/[[...slug]]/page.js | /shop | { slug: undefined } |
app/[categoryId]/[itemId]/page.js | - | { categoryId: string, itemId: string } |
params de forma síncrona: ainda funciona por compat (v15), mas está deprecated; sempre await ou use().await params no topo de um layout: impede o layout de ser prerenderizado; passe a Promise adiante e aguarde só no componente que precisa do valor.generateStaticParams cobre todo branch condicional: branches de código que só disparam para params fora da amostra não são validados no build; se acessam API runtime sem <Suspense>, falham só na primeira request real.params como tipo estreito sem validação runtime: valores vêm sempre como string/string[]/undefined, qualquer restrição (ex. enum de locale) precisa de validação explícita + notFound().[...x]) não casa com a rota sem sufixo; optional catch-all ([[...x]]) casa.fetch dentro de generateStaticParams é deduplicado automaticamente entre chamadas.generateStaticParams funciona também em Route Handlers dinâmicos (route.ts), gerando respostas de API estáticas no build.<Suspense> em torno de dado runtime (ex. cookies()) dentro de um branch condicional de params não amostrado, a primeira request real falha.params como Promise pela mesma mecânica.params no topo do layout.