useLinkStatus
useLinkStatus
钩子用于追踪 <Link>
组件的 pending 状态。您可以使用它在导航到新路由完成时向用户显示内联视觉反馈(如加载旋转图标或文字闪烁效果)。
useLinkStatus
在以下场景中特别有用:
- 预加载 (Prefetching) 被禁用或正在进行时,意味着导航被阻塞
- 目标路由是动态的 且 没有包含
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}
时,这个钩子最有用- 如果链接的路由已被预加载,pending 状态将被跳过
- 当快速连续点击多个链接时,只会显示最后一个链接的 pending 状态
- 此钩子在 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 钩子。 |