useLinkStatus for Link Pending State
Navigation isn't always instant. Slow networks, dynamic routes that can't be prefetched, or simply large payloads can create delay. useLinkStatus provides pending state specifically for <Link> navigations—no transition management required.
The hook returns { pending } and must be used inside a descendant component of the <Link>.
The Pattern
Create a child component that shows loading feedback:
'use client';
import Link, { useLinkStatus } from 'next/link';
function NavIndicator({ children }) {
const { pending } = useLinkStatus();
return (
<>
{pending ? <Spinner className="size-4" /> : null}
{children}
</>
);
}
export function NavLink({ href, children }) {
return (
<Link href={href}>
<NavIndicator>{children}</NavIndicator>
</Link>
);
}Click the link → spinner appears → navigation completes → new page renders.
When Pending Shows
The spinner appears when navigation takes time:
- Slow connections — Prefetching hasn't completed before clicking
- Dynamic routes — Routes that read
searchParamsor other dynamic data can't be fully prefetched - Large payloads — Even prefetched routes can take time to render
On fast connections with fully prefetched routes, the spinner won't appear—and that's ideal.
The Child Component Constraint
Like useFormStatus, useLinkStatus must be called from a child of the Link:
// ❌ Won't work - same component as Link
function BadLink() {
const { pending } = useLinkStatus(); // Always false
return <Link href="/page">...</Link>;
}
// ✅ Works - NavIndicator is a child inside Link
function GoodLink() {
return (
<Link href="/page">
<NavIndicator>Go to page</NavIndicator>
</Link>
);
}vs useTransition + router.push
| Approach | Use When |
|---|---|
useLinkStatus | Simple navigation feedback, declarative, works with <Link> |
useTransition + router.push | Need optimistic updates, imperative control, error handling |
Choose useLinkStatus for straightforward navigation feedback. Use useTransition when you need to update state optimistically or handle the navigation outcome programmatically.