Link vs useRouter in Next.js
Link vs useRouter in Next.js
Link vs useRouter in Next.js: The Eternal Struggle
You’ve built a Next.js app. You’ve got pages, components, buttons, and navbars.
And then it happens:
“Should I use
<Link>
oruseRouter.push()
here?”
Relax. You’re not alone. Every developer has googled this at least once (usually at 2AM).
This guide is here to finally sort it out.
TL;DR (fast answers)
| Situation | Use <Link>
| Use useRouter
|
|-----------------------------------|------------------------------------------|--------------------------------------|
| Navbar links | ✅ Yes | ❌ No |
| Buttons that go to static routes | ✅ Wrap button in <Link>
| ❌ Not needed |
| Redirect after login / submit | ❌ No | ✅ router.push()
|
| Add/replace search params | ❌ Not supported directly | ✅ router.push()
/ router.replace()
|
| Scroll control / history replace | ❌ No | ✅ Yes |
| Prefetch optimization | ✅ Built-in | ❌ Not applicable |
The Mental Model
-
<Link>
= declarative navigation.
“When the user clicks here, take them there.” You describe what should happen and let Next.js handle the details (prefetching, transitions, accessibility). -
useRouter
= imperative navigation.
“If X happens, go there.” You’re in control, calling functions to push or replace routes. Think of it like the difference between setting an alarm vs manually checking the time every five minutes.
<Link>
from next/link
Example:
import Link from "next/link";
export default function Navbar() {
return (
<nav>
<Link href="/about">About</Link>
<Link href="/contact">Contact</Link>
</nav>
);
}