跳到内容
API 参考函数useLinkStatus

useLinkStatus

useLinkStatus 钩子让你跟踪 <Link>待定 状态。当导航完成时,可以用它来提供细微的内联反馈,例如在点击的链接上显示微光效果。更推荐使用 loading.js 进行路由级别的回退,并使用预取来实现即时过渡。

useLinkStatus 在以下情况下很有用:

  • 预取 被禁用或正在进行中,这意味着导航被阻塞。
  • 目标路由是动态的 并且 不包含 loading.js 文件,该文件将允许即时导航。
app/hint.tsx
'use client'
 
import Link from 'next/link'
import { useLinkStatus } from 'next/link'
 
function Hint() {
  const { pending } = useLinkStatus()
  return (
    <span aria-hidden className={`link-hint ${pending ? 'is-pending' : ''}`} />
  )
}
 
export default function Header() {
  return (
    <header>
      <Link href="/dashboard" prefetch={false}>
        <span className="label">Dashboard</span> <Hint />
      </Link>
    </header>
  )
}

须知:

  • useLinkStatus 必须在 Link 组件的子组件中使用
  • Link 组件上设置 prefetch={false} 时,此钩子最有用。
  • 如果链接的路由已被预取,则会跳过待定状态。
  • 当快速连续点击多个链接时,只显示最后一个链接的待定状态。
  • 此钩子在 Pages Router 中不受支持,并且始终返回 { pending: false }
  • 内联指示器很容易导致布局偏移。更推荐使用固定大小、始终渲染的提示元素并切换其不透明度,或使用动画。

你可能不需要 useLinkStatus

在添加内联反馈之前,请考虑以下情况:

  • 目的地是静态的,并且在生产环境中已预取,因此可能会跳过待定阶段。
  • 路由有一个 loading.js 文件,可以通过路由级回退实现即时过渡。

导航通常很快。当你发现慢速过渡时,可以将 useLinkStatus 作为快速修复方案,然后通过预取或 loading.js 回退来迭代解决根本原因。

参数

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 (
    <span aria-hidden className={`link-hint ${pending ? 'is-pending' : ''}`} />
  )
}
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}>
          <span className="label">{link.label}</span> <LoadingIndicator />
        </Link>
      ))}
    </div>
  )
}
 
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div>
      <Menubar />
      {children}
    </div>
  )
}

优雅地处理快速导航

如果导航到新路由速度很快,用户可能会看到不必要的提示闪烁。一种改善用户体验的方法是仅在导航需要时间完成时才显示提示,即添加一个初始动画延迟(例如100毫秒)并将动画开始时设置为不可见(例如opacity: 0)。

app/styles/global.css
.link-hint {
  display: inline-block;
  width: 0.6em;
  height: 0.6em;
  margin-left: 0.25rem;
  border-radius: 9999px;
  background: currentColor;
  opacity: 0;
  visibility: hidden; /* reserve space without showing the hint */
}
 
.link-hint.is-pending {
  /* Animation 1: fade in after 100ms and keep final opacity */
  /* Animation 2: subtle pulsing while pending */
  visibility: visible;
  animation-name: fadeIn, pulse;
  animation-duration: 200ms, 1s;
  /* Appear only if navigation actually takes time */
  animation-delay: 100ms, 100ms;
  animation-timing-function: ease, ease-in-out;
  animation-iteration-count: 1, infinite;
  animation-fill-mode: forwards, none;
}
 
@keyframes fadeIn {
  to {
    opacity: 0.35;
  }
}
@keyframes pulse {
  50% {
    opacity: 0.15;
  }
}

版本历史

版本更改
v15.3.0useLinkStatus 引入。

下一步

通过阅读 API 参考文档,了解更多本页中提到的功能。