Track Link pending state, SortButton pattern, prefetch={false} for visible feedback.
The useLinkStatus hook provides pending state for <Link> navigations. It must be used inside a descendant component of Link.
Use useLinkStatus when:
loading.js'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>
);
}useLinkStatus only works inside a component rendered within <Link>prefetch={false} - If the route is prefetched, pending state is skippedbuttonVariants from shadcn/ui to style Links as buttons| 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.