Navigate with <Link>
next/link keeps layouts mounted; template.tsx remounts.
From next-best-practices, functions.md and file-conventions.md.
<a> reloads, <Link> swaps
Press +1, type a filter, then switch pages.
<a href="/reports">Bad<Link href="/reports">Good// Bad: a new document, layout state lost
<a href="/reports">Reports</a>
// Good: client transition, layout kept
import Link from 'next/link'
<Link href="/reports">Reports</Link>
layout.tsx vs template.tsx
Type a draft, press +1, then navigate.
layout.tsxKeeps statetemplate.tsxRemounts// app/(app)/template.tsx
export default function Template({ children }: { children: React.ReactNode }) {
return <div className="enter">{children}</div>
}
Active link from usePathname()
Type a path or pick one.
usePathname() → /reports/q3
Exact matchBad
pathname === hrefSegment matchGood
pathname.startsWith(`${href}/`)'use client'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
export function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
const pathname = usePathname()
const active = href === '/'
? pathname === '/'
: pathname === href || pathname.startsWith(`${href}/`)
return (
<Link href={href} aria-current={active ? 'page' : undefined} className={active ? 'active' : ''}>
{children}
</Link>
)
}
Why it matters, pros and cons
Why it matters
A plain <a> loads a new document. <Link> swaps only what changed.
Pros
- Layout state survives: counters, inputs, scroll.
- No blank frame; links prefetch in production.
template.tsxscopes per-route entrance effects.
Cons
- External sites and downloads still need a plain
<a>. - Prefetch costs bandwidth on link-heavy pages.
- Kept state can leak between routes; reset with
key.