← Back
Edit Post
Title
Description
Link pending state with useLinkStatus, child component pattern, comparison with useTransition.
Content
Markdown supported
# 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: ```tsx '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 `searchParams` or 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: ```tsx // ❌ 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.
Published
Save Changes
Cancel