Linking and navigation

Next.js · Essentials · 10 min

Fast navigation is a key Next.js benefit, and it depends on using Link and the navigation hooks correctly.

Use the `<Link>` component from next/link for internal navigation: <Link href="/blog">Blog</Link>. It renders an <a> but performs a client-side transition: only the changed segments are fetched and rendered, layouts keep their state, and the browser doesn't reload.

Prefetching: in production, links are prefetched when they enter the viewport or are hovered, so the next page is often ready before the click. How much is prefetched depends on the route; with Next.js 16's Partial Prefetching, the static App Shell of a route is prefetched by default. Pass prefetch={false} to disable it for rarely used links.

In Client Components, the hooks from next/navigation give you programmatic control:

  • useRouter() — router.push('/path'), router.replace, router.back(), router.refresh() (re-fetch server data for the current route).
  • usePathname() — the current path, e.g. to highlight the active link.
  • useSearchParams() — read query parameters.
  • useParams() — dynamic route params.

On the server (Server Components, Server Actions, Route Handlers), call redirect('/login') from next/navigation. It throws a special error that the framework handles, so code after it doesn't run.

Plain <a> tags work but cause full page loads. External links can use <a> directly.

Example

// app/ui/nav-links.tsx
'use client'

import Link from 'next/link'
import { usePathname, useRouter } from 'next/navigation'

const links = [{ href: '/', label: 'Home' }, { href: '/blog', label: 'Blog' }, { href: '/about', label: 'About' }]

export function NavLinks() {
  const pathname = usePathname()          // e.g. "/blog"
  const router = useRouter()
  return (
    <nav>
      {links.map((l) => (
        <Link key={l.href} href={l.href} className={pathname === l.href ? 'active' : ''}>
          {l.label}
        </Link>
      ))}
      <button onClick={() => router.push('/search?q=next')}>Search</button>
    </nav>
  )
}

Remember

  • <Link> does client-side transitions and prefetches in production
  • useRouter, usePathname, useSearchParams come from next/navigation (client only)
  • Use redirect() on the server; it throws and stops execution

Watch out for

  • Importing useRouter from next/router (Pages Router) in an App Router component; use next/navigation.

Check yourself

  1. Why prefer <Link href="/blog"> over <a href="/blog"> for internal links?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: nextjs.org/docs/app/getting-started/linking-and-navigating