100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
JavaScript

The Link Component and Navigation

Learn how Next.js's Link component powers fast, client-side navigation with automatic prefetching, and how to complement it with the useRouter and usePathname hooks.

Navigation & UIBeginner8 min readJul 10, 2026
Analogies

The Link component from next/link is the primary way to move between routes in a Next.js application. Instead of triggering a full browser page reload like a plain <a> tag, Link intercepts the click, swaps the page content on the client, and preserves state such as scroll position and any client-side React state that lives outside the changed route segment. This makes navigation feel instant because the browser never re-downloads the HTML document, re-parses global CSS, or re-initializes the JavaScript runtime.

🏏

Cricket analogy: Switching from Link to a bare <a> tag is like a batter walking back to the pavilion between overs instead of just crossing for a quick single — Link keeps you 'in the crease' of the app instead of restarting the whole innings.

Prefetching and Performance

In the App Router, any Link component that is visible in the viewport is automatically prefetched in the background by default, so the route's code and, for statically generated segments, its data are already available before the user even clicks. You can override this behavior with the prefetch prop: prefetch={false} disables it entirely, which is useful for routes behind authentication gates or rarely visited links where prefetching would waste bandwidth, while the default behavior in the App Router prefetches the shared layout and loading skeleton for dynamic routes without deep data fetching.

🏏

Cricket analogy: Automatic prefetching is like a wicketkeeper standing up to the stumps in anticipation of a slower ball, already positioned before the delivery arrives, rather than reacting only after the batter has played the shot.

Dynamic and Programmatic Navigation

While Link handles declarative navigation triggered by user clicks, the useRouter hook from next/navigation gives you programmatic control for cases like redirecting after a form submission or a timed logout. router.push adds a new entry to the browser history stack, while router.replace swaps the current entry, which is useful after actions like completing a checkout so users can't navigate back into a stale form. Dynamic hrefs for Link are typically built with template literals, such as href={/products/${product.id}}, letting a single Link component render correct paths for a list of items.

🏏

Cricket analogy: router.push versus router.replace is like a captain sending in a new batter after a wicket falls (push, extending the scorecard) versus a runner being substituted mid-over without altering the over count (replace, swapping in place).

tsx
'use client';

import Link from 'next/link';
import { useRouter } from 'next/navigation';

export default function ProductRow({ product }: { product: { id: string; name: string } }) {
  const router = useRouter();

  async function handleQuickBuy() {
    await fetch('/api/cart', { method: 'POST', body: JSON.stringify({ id: product.id }) });
    router.push('/checkout');
  }

  return (
    <div className="flex items-center gap-4">
      <Link href={`/products/${product.id}`} prefetch={true}>
        {product.name}
      </Link>
      <button onClick={handleQuickBuy}>Buy now</button>
    </div>
  );
}

A very common UI pattern is highlighting the currently active navigation link, and Next.js provides usePathname from next/navigation for exactly this purpose. Because it's a client hook, usePathname must be called inside a Client Component, and it returns the current URL's path segment so you can compare it against each Link's href and conditionally apply an 'active' class. Unlike the older pages router pattern that relied on router.pathname from useRouter, usePathname in the App Router returns a plain string and re-renders only the component that calls it rather than the whole page.

🏏

Cricket analogy: usePathname is like the on-field umpire signaling which end is currently 'striker's end' — every player on the field can check that single reference to know exactly where play is focused right now.

Since Next.js 13, the legacyBehavior prop and the requirement to nest a raw <a> tag inside Link were removed. You can now pass className, onClick, and other props directly to Link itself, and it renders its own anchor tag under the hood.

Replacing Link with a plain <a href="/dashboard"> tag inside your app forces a full page reload, discarding client-side state, re-fetching the entire document, and losing the performance benefits of prefetching. Only use raw <a> tags for external URLs that leave your domain.

  • Link from next/link performs client-side transitions without a full page reload.
  • App Router Links visible in the viewport are prefetched automatically unless prefetch={false} is set.
  • useRouter().push adds a history entry; router.replace swaps the current one without adding a new entry.
  • Dynamic hrefs are built with template literals, e.g. href={/products/${id}}.
  • usePathname returns the current route as a string for building active-link styling in Client Components.
  • Since Next.js 13, legacyBehavior and nested <a> tags inside Link are no longer required.
  • Use plain <a> tags only for links that navigate outside your application's domain.

Practice what you learned

Was this page helpful?

Topics covered

#JavaScript#NextJsStudyNotes#WebDevelopment#TheLinkComponentAndNavigation#Link#Component#Navigation#Client#StudyNotes#SkillVeris