Buat folder [slug] di dalam app untuk membuat dynamic route di App Router Next.js. Folder app/blog/[slug]/page.tsx otomatis menangani URL seperti /blog/hello-dunia, lalu nilai hello-dunia dibaca lewat params.slug di Server Component.
Static route memakai nama folder pasti, misalnya app/about/page.tsx hanya untuk /about. Dynamic route memakai kurung siku untuk segmen yang berubah. Search params berbeda lagi, ia membaca ?q=… lewat searchParams, bukan bagian pathname.
Hasil Akhir Cara Membuat Dynamic Route di App Router
Target akhirnya satu file menangani ratusan URL berbeda. Kamu tidak perlu membuat folder manual untuk setiap judul blog atau ID produk.
- app/blog/page.tsx menampilkan daftar artikel.
- app/blog/[slug]/page.tsx menampilkan satu artikel berdasarkan slug.
- URL /blog/hello-dunia menghasilkan params = { slug: “hello-dunia” }.
Buat Folder [slug] dan Baca Params dengan Benar
- Buat file app/blog/[slug]/page.tsx. Nama di dalam kurung harus sama dengan kunci params yang dibaca.
- Baca params sebagai props di Server Component. Di Next.js terbaru, params berupa Promise sehingga perlu await.
- Tambahkan generateStaticParams bila halaman ingin di-build statis untuk slug yang sudah diketahui.
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
return [{ slug: "hello-dunia" }, { slug: "belajar-nextjs" }];
}
export default async function BlogDetail({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
return <h1>Artikel: {slug}</h1>;
}
Gunakan useParams() hanya di Client Component dengan “use client”. Server Component tidak boleh memakai hook tersebut.
Tabel Pola Dynamic Route yang Sering Dipakai
| Pola | Contoh URL | Fungsi |
|---|---|---|
| [slug] | /blog/hello-dunia | Satu segmen dinamis |
| […slug] | /docs/a/b/c | Menangkap banyak segmen |
| [[…slug]] | /docs atau /docs/a | Catch-all opsional |
- Pakai [id] atau [slug] untuk detail produk, artikel, atau profil.
- Pakai […slug] untuk dokumentasi bertingkat atau kategori berlapis.
- Pakai [[…slug]] bila rute induk tanpa slug tetap harus tampil.
Validasi Data dan Tangani Slug Tidak Ditemukan
Validasi slug di server sebelum query database atau fetch API. Slug dari URL selalu string dan bisa dimanipulasi pengguna.
import { notFound } from "next/navigation";
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
if (!slug || slug.length > 100) notFound();
return <p>Slug valid: {slug}</p>;
}
- params undefined: biasanya nama folder dan kunci params tidak sama.
- Fetch gagal: tangani respons kosong dengan notFound(), bukan redirect asal.
- Salah nama folder: gunakan [slug], bukan {slug} atau (slug).
FAQ
Bagaimana cara baca id dari URL di Server Component?
Buat app/produk/[id]/page.tsx, lalu baca lewat await params untuk mendapatkan params.id.
Kapan dynamic route butuh generateStaticParams?
Pakai saat slug sudah diketahui waktu build dan halaman boleh disajikan statis agar lebih cepat.
Apakah dynamic route harus pakai use client?
Tidak, Server Component justru direkomendasikan karena slug bisa dibaca langsung dari params.