Menu

useLinkStatus

useLinkStatus フックを使用すると、<Link>pending状態を追跡できます。これを使用して、ナビゲーション完了中にクリックされたリンク上のシマー効果など、微妙でインラインフィードバックを提供します。ルートレベルの loading.js フォールバックとプリフェッチングを優先して、即座のトランジションを実現してください。

useLinkStatus は以下の場合に便利です。

  • プリフェッチングが無効になっているか進行中でナビゲーションがブロックされている場合。
  • 宛先ルートが動的かつ即座のナビゲーションを可能にする loading.js ファイルが含まれていない場合。
app/hint.tsx
TypeScript
'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>
  )
}

補足

  • useLinkStatusLink コンポーネントの子孫コンポーネント内で使用する必要があります
  • このフックは Link コンポーネントで prefetch={false} が設定されている場合に最も有用です
  • リンク先ルートがプリフェッチされている場合、pending 状態はスキップされます
  • 短時間に複数のリンクをクリックすると、最後のリンクの pending 状態のみが表示されます
  • このフックは Pages Router ではサポートされておらず、常に { pending: false } を返します
  • インラインインジケータはレイアウトシフトを容易に引き起こします。固定サイズで常にレンダリングされるヒント要素を優先し、その不透明度を切り替えるか、アニメーションを使用してください。

useLinkStatus が不要な場合もあります

インラインフィードバックを追加する前に、以下の点を確認してください。

  • 宛先は静的でプロダクション環境でプリフェッチされているため、pending フェーズはスキップされる可能性があります。
  • ルートに loading.js ファイルがあり、ルートレベルのフォールバックで即座のトランジションが可能です。

通常、ナビゲーションは高速です。遅いトランジションを特定したら useLinkStatus をクイック パッチとして使用し、プリフェッチングまたは loading.js フォールバックで根本原因を修正するために反復処理してください。

パラメータ

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

高速ナビゲーションを適切に処理する

新しいルートへのナビゲーションが高速の場合、ユーザーには不必要なヒントのフラッシュが表示される場合があります。ユーザーエクスペリエンスを向上させ、ナビゲーションが完了に時間がかかる場合のみヒントを表示する方法の 1 つは、初期アニメーション遅延(例:100ms)を追加し、アニメーションを非表示の状態(例: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; /* スペースを確保しつつ、ヒントを表示しない */
}
 
.link-hint.is-pending {
  /* アニメーション 1:100ms 後にフェードインしており、最終的な不透明度を保持 */
  /* アニメーション 2:pending 中の微妙なパルス */
  visibility: visible;
  animation-name: fadeIn, pulse;
  animation-duration: 200ms, 1s;
  /* ナビゲーションが実際に時間がかかる場合のみ表示 */
  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