Buat folder bernama [[…slug]] di dalam App Router agar satu file page.tsx menangani URL tanpa segmen, satu segmen, dan banyak segmen. Kesalahan yang paling sering terjadi adalah memakai […slug] lalu bingung kenapa /docs menampilkan 404. Pola tanpa kurung ganda wajib punya minimal satu segmen.
Bedanya Catch All dan Optional Catch All di App Router
Next.js menyediakan dua pola untuk URL dinamis bertingkat. […slug] hanya cocok untuk URL yang sudah pasti punya isi. [[…slug]] menambahkan kemampuan menangkap induknya sendiri.
- […slug] pada /docs/[…slug] menolak /docs dan hanya menerima /docs/a atau /docs/a/b.
- [[…slug]] pada /docs/[[…slug]] menerima /docs, /docs/a, dan /docs/a/b dalam satu page.
- params.slug selalu berupa array string. Pada optional catch all, nilainya undefined saat pengguna membuka URL induk.
- Pakai pola opsional untuk dokumentasi, kategori bertingkat, atau halaman bantuan dengan struktur tidak tetap.
Langkah Membuat Folder [[…slug]] Sampai Page Terbaca
Struktur ini memakai Server Component bawaan App Router, jadi tidak perlu use client atau useParams.
- Buat folder app/docs/[[…slug]]/page.tsx. Nama kurung ganda wajib tepat.
- Baca params.slug dengan nilai default array kosong untuk menghindari error saat undefined.
- Buat percabangan render untuk nol segmen, satu segmen, dan lebih dari satu segmen.
- Buka /docs, /docs/a, lalu /docs/a/b dan pastikan ketiganya me-render page yang sama dengan konten berbeda.
Contoh Kode Page dan Tabel Pola URL
type Props = {
params: { slug?: string[] };
};
export default function DocsPage({ params }: Props) {
const slug = params.slug ?? [];
if (slug.length === 0) {
return <h1>Dokumentasi utama</h1>;
}
if (slug.length === 1) {
return <h1>Topik: {slug[0]}</h1>;
}
return <h1>Jalur: {slug.join(" / ")}</h1>;
}
| URL | Nilai slug | Hasil render |
|---|---|---|
| /docs | undefined | Halaman induk |
| /docs/a | [“a”] | Satu topik |
| /docs/a/b | [“a”, “b”] | Jalur bertingkat |
- Nama folder harus [[…slug]], bukan […slug] atau [slug].
- Normalisasi params.slug ke array kosong sebelum memanggil length, map, atau join.
- Jangan menaruh file page.tsx statis di /docs/page.tsx bersamaan tanpa rencana, karena route statis mendapat prioritas lebih tinggi.
FAQ
Apakah [[…slug]] bisa menangani / tanpa segmen?
Ya, slug bernilai undefined lalu tampilkan halaman induk.
Kapan optional catch all tidak cocok?
Bila hanya satu level ID, pakai [id] agar route lebih tegas.
Kenapa route statis tidak terpanggil?
Karena ada folder statis dengan nama sama yang prioritasnya lebih tinggi.