useLinkStatus

Le hook useLinkStatus permet de suivre l'état pending (en attente) d'un composant <Link>. Vous pouvez l'utiliser pour afficher un retour visuel en ligne à l'utilisateur (comme des spinners ou des effets de texte) pendant la navigation vers une nouvelle route.

useLinkStatus est utile lorsque :

  • Le préchargement (prefetching) est désactivé ou en cours, ce qui bloque la navigation.
  • La route de destination est dynamique et ne comprend pas de fichier loading.js qui permettrait une navigation instantanée.
'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>
  )
}

Bon à savoir :

  • useLinkStatus doit être utilisé dans un composant enfant d'un composant Link
  • Le hook est particulièrement utile lorsque prefetch={false} est défini sur le composant Link
  • Si la route liée a été préchargée, l'état pending sera ignoré
  • Lorsque plusieurs liens sont cliqués rapidement, seul l'état pending du dernier lien est affiché
  • Ce hook n'est pas pris en charge dans le routeur Pages et retournera toujours { pending: false }

Paramètres

const { pending } = useLinkStatus()

useLinkStatus ne prend aucun paramètre.

Valeur retournée

useLinkStatus retourne un objet avec une seule propriété :

PropriétéTypeDescription
pendingbooleantrue avant la mise à jour de l'historique, false après

Exemple

Indicateur de chargement en ligne

Il est utile d'ajouter un retour visuel indiquant qu'une navigation est en cours, au cas où l'utilisateur clique sur un lien avant que le préchargement ne soit terminé.

'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: 'Electronique' },
  { href: '/shop/clothing', label: 'Vêtements' },
  { href: '/shop/books', label: 'Livres' },
]

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: 'Electronique' },
  { href: '/shop/clothing', label: 'Vêtements' },
  { href: '/shop/books', label: 'Livres' },
]

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>
  )
}

Gestion fluide des navigations rapides

Si la navigation vers une nouvelle route est rapide, les utilisateurs peuvent voir un flash inutile de l'indicateur de chargement. Une façon d'améliorer l'expérience utilisateur et de n'afficher l'indicateur de chargement que lorsque la navigation prend du temps est d'ajouter un délai d'animation initial (par exemple 100ms) et de démarrer l'animation comme invisible (par exemple opacity: 0).

app/styles/global.css
.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);
  }
}
VersionModifications
v15.3.0Introduction de useLinkStatus.