useLinkStatus

Der useLinkStatus-Hook ermöglicht es Ihnen, den Pending-Status eines <Link>-Elements zu verfolgen. Sie können ihn verwenden, um dem Benutzer während der Navigation zu einer neuen Route visuelles Feedback anzuzeigen (wie Ladespinner oder Textanimationen).

useLinkStatus ist nützlich, wenn:

  • Prefetching deaktiviert ist oder im Gange ist, was bedeutet, dass die Navigation blockiert ist.
  • Die Zielroute dynamisch ist und keine loading.js-Datei enthält, die eine sofortige Navigation ermöglichen würde.
'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>
  )
}

Wichtig zu wissen:

  • useLinkStatus muss innerhalb einer untergeordneten Komponente eines Link-Elements verwendet werden
  • Der Hook ist besonders nützlich, wenn prefetch={false} für das Link-Element gesetzt ist
  • Wenn die verlinkte Route bereits geprefetched wurde, wird der Pending-Status übersprungen
  • Bei mehrfachem Klicken auf Links in schneller Folge wird nur der Pending-Status des letzten Links angezeigt
  • Dieser Hook wird im Pages Router nicht unterstützt und gibt immer { pending: false } zurück

Parameter

const { pending } = useLinkStatus()

useLinkStatus benötigt keine Parameter.

Rückgabewerte

useLinkStatus gibt ein Objekt mit einer einzelnen Eigenschaft zurück:

EigenschaftTypBeschreibung
pendingbooleantrue vor dem History-Update, false danach

Beispiel

Inline-Ladeindikator

Es ist hilfreich, visuelles Feedback anzuzeigen, wenn eine Navigation stattfindet, falls der Benutzer auf einen Link klickt, bevor das Prefetching abgeschlossen ist.

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

Umgang mit schnellen Navigationen

Wenn die Navigation zu einer neuen Route schnell abgeschlossen ist, könnten Benutzer ein unnötiges Aufblitzen des Ladeindikators sehen. Eine Möglichkeit, die Benutzererfahrung zu verbessern und den Ladeindikator nur anzuzeigen, wenn die Navigation länger dauert, besteht darin, eine anfängliche Animationsverzögerung (z.B. 100ms) hinzuzufügen und die Animation zunächst unsichtbar zu starten (z.B. 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);
  }
}
VersionÄnderungen
v15.3.0useLinkStatus eingeführt.