Cara membuat link active Next.js paling tepat adalah membaca pathname lewat usePathname dari next/navigation di Client Component khusus navigasi. Layout dan halaman tetap Server Component, hanya navbar yang memakai use client. Pola ini mencegah seluruh layout ikut menjadi client.
Pola Link Active yang Benar di App Router
App Router memisahkan rendering server dan browser. Link biasa bisa dirender dari Server Component, tetapi pengecekan menu aktif butuh pathname saat ini.
- Gunakan Server Component untuk
layout.tsxdan konten halaman. - Buat Client Component kecil bernama
NavLinkskhusus menu. - Ambil rute dengan
usePathname()darinext/navigation. - Jangan pakai
useRoutergaya Pages Router untuk kebutuhan ini. - Gunakan pencocokan exact untuk
/,startsWithuntuk segmen induk.
Langkah Membuat Navbar dengan Link Aktif
1. Buat array berisi href dan label, misalnya /, /tentang, /blog.
2. Buat file NavLinks.tsx dengan use client di baris pertama.
3. Panggil const pathname = usePathname() di dalam komponen tersebut.
4. Bandingkan setiap href dengan pathname untuk menentukan class aktif seperti text-blue-600 font-semibold.
5. Render Link dari next/link dengan class kondisional, lalu pasang NavLinks di layout.tsx.
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
const menus = [
{ href: "/", label: "Beranda" },
{ href: "/blog", label: "Blog" },
];
function isActive(pathname: string, href: string) {
if (href === "/") return pathname === "/";
return pathname === href || pathname.startsWith(href + "/");
}
export default function NavLinks() {
const pathname = usePathname();
return (
<nav>
{menus.map((m) => (
<Link
key={m.href}
href={m.href}
className={isActive(pathname, m.href) ? "active" : ""}
>
{m.label}
</Link>
))}
</nav>
);
}
Perbandingan Pencocokan Pathname
| Masalah | Penyebab | Solusi |
|---|---|---|
| Semua menu aktif di Home | /tentang dianggap cocok |
Pakai exact untuk / |
/blog/slug tidak aktif |
Hanya cek sama persis | Pakai startsWith("/blog/") |
| Trailing slash tidak cocok | /blog/ beda string |
Normalisasi slash akhir |
- Rute
/hanya aktif bila pathname persis/. - Rute
/blogaktif untuk/blogdan/blog/slug-pertama. - Rute
/dashboardaktif untuk/dashboard,/dashboard/settings, dan subrute lain.
FAQ
Apakah usePathname bisa dipakai di Server Component?
Tidak. Bungkus menu dalam Client Component tersendiri, biarkan layout tetap server.
Bagaimana handle dynamic route seperti /produk/[id]?
Cek dengan startsWith("/produk/") agar semua ID produk tetap menyalakan menu Produk.
Kenapa active state tidak update saat pindah halaman?
Komponen membaca pathname dari props lama atau state basi, panggil usePathname() langsung di komponen menu.