跳到主要内容

useLinkStatus

useLinkStatus 钩子让你可以跟踪 <Link>待处理状态。你可以使用它在导航到新路由完成时向用户显示内联视觉反馈(如旋转器或文本闪烁)。

useLinkStatus 在以下情况下很有用:

  • 预取 被禁用或正在进行,意味着导航被阻塞。
  • 目标路由是动态的并且不包含允许即时导航的 loading.js 文件。
app/loading-indicator.tsx
'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
}
app/header.tsx
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 路由器中不受支持,将始终返回 { pending: false }

参数

const { pending } = useLinkStatus()

useLinkStatus 不接受任何参数。

返回值

useLinkStatus 返回一个具有单个属性的对象:

属性类型描述
pendingboolean历史更新前为 true,更新后为 false

示例

内联加载指示器

在用户点击链接但预取尚未完成的情况下,添加导航正在进行的视觉反馈很有帮助。

app/components/loading-indicator.tsx
'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
}
app/shop/layout.tsx
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>
)
}

优雅处理快速导航

如果导航到新路由很快,用户可能会看到不必要的加载指示器闪烁。改善用户体验并只在导航需要时间完成时显示加载指示器的一种方法是添加初始动画延迟(例如 100ms)并以不可见状态开始动画(例如 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