useLinkStatus
El hook useLinkStatus
permite rastrear el estado pendiente de un <Link>
. Puedes usarlo para mostrar retroalimentación visual en línea al usuario (como spinners o efectos de texto) mientras se completa la navegación a una nueva ruta.
useLinkStatus
es útil cuando:
- El prefetching está deshabilitado o en progreso, lo que significa que la navegación está bloqueada.
- La ruta de destino es dinámica y no incluye un archivo
loading.js
que permitiría una navegación instantánea.
'use client'
import { useLinkStatus } from 'next/link'
export default function LoadingIndicator() {
const { pending } = useLinkStatus()
return pending ? (
<div role="status" aria-label="Loading" className="spinner" />
) : null
}
'use client'
import { useLinkStatus } from 'next/link'
export default function LoadingIndicator() {
const { pending } = useLinkStatus()
return pending ? (
<div role="status" aria-label="Loading" className="spinner" />
) : null
}
import Link from 'next/link'
import LoadingIndicator from './loading-indicator'
export default function Header() {
return (
<header>
<Link href="/dashboard" prefetch={false}>
Dashboard <LoadingIndicator />
</Link>
</header>
)
}
import Link from 'next/link'
import LoadingIndicator from './loading-indicator'
export default function Header() {
return (
<header>
<Link href="/dashboard" prefetch={false}>
Dashboard <LoadingIndicator />
</Link>
</header>
)
}
Importante:
useLinkStatus
debe usarse dentro de un componente descendiente de un componenteLink
- El hook es más útil cuando se establece
prefetch={false}
en el componenteLink
- Si la ruta enlazada ha sido prefetcheada, se omitirá el estado pendiente
- Al hacer clic en múltiples enlaces rápidamente, solo se muestra el estado pendiente del último enlace
- Este hook no es compatible con el Pages Router y siempre devolverá
{ pending: false }
Parámetros
const { pending } = useLinkStatus()
useLinkStatus
no recibe parámetros.
Valores devueltos
useLinkStatus
devuelve un objeto con una sola propiedad:
Propiedad | Tipo | Descripción |
---|---|---|
pending | boolean | true antes de actualizar el historial, false después |
Ejemplo
Indicador de carga en línea
Es útil agregar retroalimentación visual que indique que la navegación está ocurriendo en caso de que el usuario haga clic en un enlace antes de que se complete el prefetching.
'use client'
import { useLinkStatus } from 'next/link'
export default function LoadingIndicator() {
const { pending } = useLinkStatus()
return pending ? (
<div role="status" aria-label="Loading" className="spinner" />
) : null
}
'use client'
import { useLinkStatus } from 'next/link'
export default function LoadingIndicator() {
const { pending } = useLinkStatus()
return pending ? (
<div role="status" aria-label="Loading" className="spinner" />
) : null
}
import Link from 'next/link'
import LoadingIndicator from './components/loading-indicator'
const links = [
{ href: '/shop/electronics', label: 'Electronics' },
{ href: '/shop/clothing', label: 'Clothing' },
{ href: '/shop/books', label: 'Books' },
]
function Menubar() {
return (
<div>
{links.map((link) => (
<Link key={link.label} href={link.href}>
{link.label} <LoadingIndicator />
</Link>
))}
</div>
)
}
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div>
<Menubar />
{children}
</div>
)
}
import Link from 'next/link'
import LoadingIndicator from './components/loading-indicator'
const links = [
{ href: '/shop/electronics', label: 'Electronics' },
{ href: '/shop/clothing', label: 'Clothing' },
{ href: '/shop/books', label: 'Books' },
]
function Menubar() {
return (
<div>
{links.map((link) => (
<Link key={link.label} href={link.href}>
{link.label} <LoadingIndicator />
</Link>
))}
</div>
)
}
export default function Layout({ children }) {
return (
<div>
<Menubar />
{children}
</div>
)
}
Manejo elegante de navegación rápida
Si la navegación a una nueva ruta es rápida, los usuarios pueden ver un destello innecesario del indicador de carga. Una forma de mejorar la experiencia del usuario y solo mostrar el indicador de carga cuando la navegación tarda en completarse es agregar un retraso inicial en la animación (ej. 100ms) y comenzar la animación como invisible (ej. opacity: 0
).
.spinner {
/* ... */
opacity: 0;
animation:
fadeIn 500ms 100ms forwards,
rotate 1s linear infinite;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes rotate {
to {
transform: rotate(360deg);
}
}
Versión | Cambios |
---|---|
v15.3.0 | Se introdujo useLinkStatus . |