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 返回一个带有单个属性的对象
| 属性 | 类型 | 描述 |
|---|---|---|
| pending | boolean | 在历史记录更新之前为 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.0 | useLinkStatus 引入。 |
这有帮助吗?