useLinkStatus
useLinkStatus フックは、<Link> のpending状態を追跡することができます。これを使用して、新しいルートへのナビゲーションが完了するまでの間、ユーザーにインラインの視覚的フィードバック(スピナーやテキストのきらめきなど)を表示することができます。
useLinkStatus が役立つのは以下の場合です:
- Prefetching が無効化されているか、進行中でナビゲーションがブロックされている場合
- 目的地のルートが動的で、即時ナビゲーションを可能にする
loading.jsファイルが含まれていない場合
- TypeScript
- JavaScript
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/loading-indicator.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
}
- TypeScript
- JavaScript
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>
)
}
app/header.js
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>
)
}
Good to know:
useLinkStatusはLinkコンポーネントの子孫コンポーネント内で使用する必要があります- このフックは、
Linkコンポーネントにprefetch={false}が設定されている場合に最も有用です- リンクされたルートが事前取得されている場合、pending 状態はスキップされます
- 短時間で複数のリンクをクリックした場合、最後のリンクの pending 状態のみが表示されます
- このフックは Pages Router ではサポートされておらず、常に
{ pending: false }を返します
パラメータ
const { pending } = useLinkStatus()
useLinkStatus はパラメータを受け取りません。
戻り値
useLinkStatus は、1つのプロパティを持つオブジェクトを返します:
| プロパティ | 型 | 説明 |
|---|---|---|
| pending | boolean | 履歴が更新される前は true、更新後は false |
例
インラインのローディングインジケーター
ユーザーが事前取得が完了する前にリンクをクリックした場合、ナビゲーションが行われていることを示す視覚的フィードバックを追加することは有用です。
- TypeScript
- JavaScript
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/components/loading-indicator.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
}
- TypeScript
- JavaScript
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>
)
}
app/shop/layout.js
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>
)
}
高速ナビゲーションの優雅な処理
新しいルートへのナビゲーションが速い場合、ユーザーは不要なローディングインジケーターのフラッシュを見ることがあります。ユーザーエクスペリエンスを向上させ、ナビゲーションが完了するのに時間がかかる場合にのみローディングインジケーターを表示するための1つの方法は、初期アニメーション遅延(例: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 が導入されました。 |