useLinkStatus

Хук useLinkStatus позволяет отслеживать состояние ожидания компонента <Link>. Вы можете использовать его для отображения визуальной обратной связи пользователю (например, спиннеров или мерцания текста) во время перехода на новый маршрут.

useLinkStatus полезен в следующих случаях:

  • Когда префетчинг отключен или выполняется, что блокирует навигацию.
  • Когда целевой маршрут является динамическим и не включает файл loading.js, который позволил бы мгновенную навигацию.
'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>
  )
}

Важно знать:

  • useLinkStatus должен использоваться внутри компонента-потомка компонента Link
  • Хук наиболее полезен, когда для компонента Link установлено prefetch={false}
  • Если маршрут был префетчен, состояние ожидания будет пропущено
  • При быстром последовательном клике по нескольким ссылкам отображается только состояние ожидания последней ссылки
  • Этот хук не поддерживается в Pages Router и всегда возвращает { pending: false }

Параметры

const { pending } = useLinkStatus()

useLinkStatus не принимает параметров.

Возвращаемое значение

useLinkStatus возвращает объект с одним свойством:

СвойствоТипОписание
pendingbooleantrue до обновления истории, false после

Пример

Индикатор загрузки в строке

Полезно добавлять визуальную обратную связь о том, что происходит навигация, если пользователь кликает по ссылке до завершения префетчинга.

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

Плавная обработка быстрой навигации

Если переход на новый маршрут происходит быстро, пользователи могут увидеть ненужное мелькание индикатора загрузки. Один из способов улучшить пользовательский опыт — показывать индикатор загрузки только тогда, когда навигация занимает больше времени. Для этого можно добавить начальную задержку анимации (например, 100 мс) и начинать анимацию как невидимую (например, 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);
  }
}
ВерсияИзменения
v15.3.0Добавлен хук useLinkStatus.