← Back to blog

useLinkStatus for Link Pending State

The useLinkStatus hook provides pending state for <Link> navigations. It must be used inside a descendant component of Link.

When to Use

Use useLinkStatus when:

  • Prefetching is disabled or in progress
  • The destination route is dynamic and doesn't have a loading.js
  • You want inline feedback (spinner, shimmer) on the clicked link itself

The Pattern

'use client'; import Link, { useLinkStatus } from 'next/link'; import { Loader2, ArrowUpDown } from 'lucide-react'; function SortIndicator({ icon: Icon, label }: { icon: typeof ArrowUpDown; label: string }) { const { pending } = useLinkStatus(); return ( <> {pending ? <Loader2 className="size-4 animate-spin" /> : <Icon className="size-4" />} <span>{label}</span> </> ); } export function SortButton() { return ( <Link href="/dashboard?sort=newest" prefetch={false} className="..."> <SortIndicator icon={ArrowUpDown} label="Newest" /> </Link> ); }

Key Points

  1. Must be a Link descendant - useLinkStatus only works inside a component rendered within <Link>
  2. Use prefetch={false} - If the route is prefetched, pending state is skipped
  3. Extract to child component - The hook tracks the parent Link's navigation state
  4. Style as Link - Use buttonVariants from shadcn/ui to style Links as buttons

vs useTransition + router.push

| Approach | Pros | Cons | |----------|------|------| | useLinkStatus | Simpler, no state management, declarative | Must use <Link>, no optimistic updates | | useTransition + router.push | Full control, optimistic updates possible | More boilerplate, imperative |

Choose useLinkStatus for simple navigation feedback. Use useTransition when you need optimistic state updates during navigation.

March 5, 2026257 words