Menu

useLinkStatus

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

useLinkStatus 在以下情况下很有用:

  • 预取被禁用或正在进行中,意味着导航被阻塞。
  • 目标路由是动态的并且没有包含 loading.js 文件来允许即时导航。
app/loading-indicator.tsx
TypeScript
'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
TypeScript
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 返回一个带有单个属性的对象:

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

示例

内联加载指示器

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

app/components/loading-indicator.tsx
TypeScript
'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
TypeScript
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

Next Steps

通过阅读 API 参考了解本页提到的功能的更多信息。