Dynamic Route — [id], [...slug], [[...slug]] — farqlari

~20 daq · Next.js · Routing Chuqurroq

Muammodan boshlaylik

Siz blog yozdingiz. 1000 ta post bor. Har biri uchun alohida papka yaratib bo'lmaydi:

app/blog/post-1/page.tsx
app/blog/post-2/page.tsx
app/blog/post-3/page.tsx
... (1000 ta)

Bu mantiqsiz. Buning uchun dynamic route — bitta papka, istalgan qiymat uchun ishlaydi.


[id] — bitta segment

Papka nomini kvadrat qavsga olish — o'sha segment dynamic bo'ladi:

app/
└── blog/
    └── [slug]/
        └── page.tsx   →  /blog/har-qanday-narsa
// app/blog/[slug]/page.tsx
export default async function BlogPost({ params }) {
  const { slug } = await params
  // /blog/nextjs-kirish → slug = "nextjs-kirish"
  // /blog/react-hooks  → slug = "react-hooks"

  const post = await db.getPost(slug)
  return <article><h1>{post.title}</h1></article>
}

Bir nechta dynamic segment:

app/shop/[category]/[id]/page.tsx
→ /shop/electronics/42
→ params = { category: "electronics", id: "42" }

[...slug] — catch-all

Nechta segment bo'lishini oldindan bilmasangiz — [...slug]:

app/docs/[...slug]/page.tsx
→ /docs/getting-started          → slug = ["getting-started"]
→ /docs/api/components/button    → slug = ["api", "components", "button"]
→ /docs                          → 404! (slug bo'sh bo'lmaydi)
// app/docs/[...slug]/page.tsx
export default async function DocsPage({ params }) {
  const { slug } = await params
  // slug — massiv: ["api", "components", "button"]

  const path = slug.join('/')  // "api/components/button"
  const doc  = await getDoc(path)

  return <div>{doc.content}</div>
}

/docs ga kirganda — 404. Chunki [...slug] kamida bitta segment talab qiladi.


[[...slug]] — optional catch-all

/docs ham ishlashi kerak bo'lsa — ikki kvadrat qavs:

app/docs/[[...slug]]/page.tsx
→ /docs                          → slug = undefined
→ /docs/getting-started          → slug = ["getting-started"]
→ /docs/api/components/button    → slug = ["api", "components", "button"]
// app/docs/[[...slug]]/page.tsx
export default async function DocsPage({ params }) {
  const { slug } = await params
  // /docs        → slug = undefined
  // /docs/intro  → slug = ["intro"]

  if (!slug) {
    return <h1>Hujjatlar bosh sahifasi</h1>
  }

  const doc = await getDoc(slug.join('/'))
  return <div>{doc.content}</div>
}

Static va Dynamic birga — ustunlik tartibi

Bir xil darajada static va dynamic route bo'lsa — static ustun:

app/blog/new/page.tsx        →  /blog/new   (static — ustun)
app/blog/[slug]/page.tsx     →  /blog/new   (dynamic — ishlamaydi)

/blog/new ga kirganda — new/page.tsx ishlaydi, [slug] emas.

app/blog/
├── new/
│   └── page.tsx    →  /blog/new  (static, ustun)
└── [slug]/
    └── page.tsx    →  /blog/react-hooks, /blog/nextjs (dynamic)

generateStaticParams — dynamic route uchun SSG

Dynamic route ni build vaqtida statik yaratish uchun:

// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await db.getAllPosts()
  return posts.map(post => ({ slug: post.slug }))
}

// Catch-all uchun
// app/docs/[...slug]/page.tsx
export async function generateStaticParams() {
  const docs = await getAllDocs()
  return docs.map(doc => ({
    slug: doc.path.split('/')  // ["api", "components", "button"]
  }))
}

Tez-tez uchraydigan xatolar

1. params ni await qilmaslik (Next.js 15+)

// ❌
export default function Page({ params }) {
  const { id } = params  // xato! Next.js 15 da params — Promise
}

// ✅
export default async function Page({ params }) {
  const { id } = await params
}

2. [...slug] da /docs ga kirish — 404

// ❌ — /docs ga kirsa 404
app/docs/[...slug]/page.tsx

// ✅ — /docs ham ishlaydi
app/docs/[[...slug]]/page.tsx

3. slug massiv ekanini unutish

// ❌ — slug massiv, string emas
const { slug } = await params
const doc = await getDoc(slug)  // xato! slug = ["api", "button"]

// ✅
const doc = await getDoc(slug.join('/'))  // "api/button"

4. Static va dynamic nomlar to'qnashishi

// ❌ — /blog/new ham [slug] ga tushadi deb o'ylash
app/blog/[slug]/page.tsx  →  /blog/new  (new/page.tsx bo'lmasa)

// ✅ — alohida static route yarating
app/blog/new/page.tsx     →  /blog/new  (static, ustun)
app/blog/[slug]/page.tsx  →  /blog/react-hooks

Xulosa

[id]         → bitta segment: /products/42
[...slug]    → bir yoki ko'p segment: /docs/api/button
[[...slug]]  → nol yoki ko'p segment: /docs, /docs/api/button

params       → Next.js 15 da await kerak
slug         → massiv, join('/') bilan string ga aylantirish
Static route → dynamic dan ustun (/blog/new > /blog/[slug])

Keyingi dars

25-dars: Route Group — (group) — URL ga ta'sir qilmasdan guruhlash

Papkalarni URL ga kirmagan holda guruhlash — turli layoutlar, turli middleware lar uchun.