Navigating Between Pages with Link
Use Link from next/link instead of a plain <a> for internal routes. Link does client-side navigation — no full page reload — and can prefetch the next page in the background.
next/link — client navigation
Use Link from next/link instead of a plain <a> for internal routes. Link does client-side navigation — no full page reload — and can prefetch the next page in the background.
For external URLs (https://...), a normal <a> is fine. For your own app paths, prefer Link.
Real-life example: Link is taking the metro between stations. A full <a> reload is getting off, walking home, and catching another train from scratch.
import Link from "next/link";
export default function SiteNav() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/courses">Courses</Link>
<Link href="/courses/nextjs">Next.js course</Link>
<Link href="/dashboard/settings">Settings</Link>
{/* External — use <a> */}
<a href="https://rishtaara.com" target="_blank" rel="noreferrer">
Rishtaara
</a>
</nav>
);
}useRouter — navigate from Client Components
When a button or form should change routes in code (after login, after save), use useRouter from next/navigation inside a Client Component ("use client").
router.push goes forward (adds history). router.replace swaps the current entry (good after login so Back does not return to the login form). router.back() goes back.
Real-life example: router.push is opening a new browser tab of history. router.replace is editing the current sticky note so the old page is gone from the stack.
- Import from next/navigation (App Router), not next/router (Pages Router)
- Only in Client Components — or call redirect() on the server instead
- router.refresh() revalidates Server Component data without changing the URL
"use client";
import { useRouter } from "next/navigation";
export default function LoginButton() {
const router = useRouter();
async function handleLogin() {
// pretend auth succeeded
await fetch("/api/login", { method: "POST" });
router.replace("/dashboard");
}
return (
<button type="button" onClick={handleLogin}>
Log in to Rishtaara
</button>
);
}Prefetching — faster next clicks
In production, Link prefetches linked routes when they enter the viewport (when possible). The user clicks and the page often feels instant because the RSC payload was already fetched.
You can disable prefetch with prefetch={false} for rare or heavy pages. In development, prefetch behavior can differ — trust production for real feel.
Real-life example: Prefetch is a waiter bringing the dessert menu before you ask — when you say yes, the order is already half ready.
import Link from "next/link";
export default function CourseLinks() {
return (
<>
{/* Default: prefetch when visible (production) */}
<Link href="/courses/nextjs">Next.js</Link>
{/* Skip prefetch for a heavy admin page */}
<Link href="/admin/reports" prefetch={false}>
Admin reports
</Link>
</>
);
}