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
возвращает объект с одним свойством:
Свойство | Тип | Описание |
---|---|---|
pending | boolean | true до обновления истории, 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
).
.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 . |