リンクとナビゲーション

Next.jsでは、ルート間を移動する方法が2つあります:

このページでは、<Link>useRouter()の使用方法を解説し、ナビゲーションの仕組みについて詳しく掘り下げます。

<Link>コンポーネント

<Link>はHTMLの<a>タグを拡張した組み込みコンポーネントで、プリフェッチとクライアントサイドのルート間ナビゲーションを提供します。Next.jsでルート間を移動する主要な方法です。

next/linkからインポートし、hrefプロパティをコンポーネントに渡すことで使用できます:

import Link from 'next/link'

export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}
import Link from 'next/link'

export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}

<Link>には他のオプションプロパティも渡せます。詳細はAPIリファレンスをご覧ください。

使用例

ダイナミックセグメントへのリンク

ダイナミックセグメントにリンクする場合、テンプレートリテラルと補間を使用してリンクリストを生成できます。例えば、ブログ記事のリストを生成する場合:

app/blog/PostList.js
import Link from 'next/link'

export default function PostList({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}

アクティブリンクの確認

usePathname()を使用してリンクがアクティブかどうかを判断できます。例えば、アクティブリンクにクラスを追加するには、現在のpathnameがリンクのhrefと一致するか確認します:

'use client'

import { usePathname } from 'next/navigation'
import Link from 'next/link'

export function Links() {
  const pathname = usePathname()

  return (
    <nav>
      <ul>
        <li>
          <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
            ホーム
          </Link>
        </li>
        <li>
          <Link
            className={`link ${pathname === '/about' ? 'active' : ''}`}
            href="/about"
          >
            アバウト
          </Link>
        </li>
      </ul>
    </nav>
  )
}
'use client'

import { usePathname } from 'next/navigation'
import Link from 'next/link'

export function Links() {
  const pathname = usePathname()

  return (
    <nav>
      <ul>
        <li>
          <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
            ホーム
          </Link>
        </li>
        <li>
          <Link
            className={`link ${pathname === '/about' ? 'active' : ''}`}
            href="/about"
          >
            アバウト
          </Link>
        </li>
      </ul>
    </nav>
  )
}

idへのスクロール

Next.js App Routerのデフォルト動作は、新しいルートのトップにスクロールするか、前後ナビゲーションでスクロール位置を維持します。

ナビゲーション時に特定のidにスクロールしたい場合、URLに#ハッシュリンクを追加するか、hrefプロパティにハッシュリンクを渡せます。これは<Link><a>要素にレンダリングされるため可能です。

<Link href="/dashboard#settings">設定</Link>

// 出力
<a href="/dashboard#settings">設定</a>

スクロール復元の無効化

Next.js App Routerのデフォルト動作は、新しいルートのトップにスクロールするか、前後ナビゲーションでスクロール位置を維持します。この動作を無効化したい場合、<Link>コンポーネントにscroll={false}を渡すか、router.push()またはrouter.replace()scroll: falseを渡せます。

// next/link
<Link href="/dashboard" scroll={false}>
  ダッシュボード
</Link>
// useRouter
import { useRouter } from 'next/navigation'

const router = useRouter()

router.push('/dashboard', { scroll: false })

useRouter()フック

useRouterフックを使用すると、プログラムでルートを変更できます。

このフックはクライアントコンポーネント内でのみ使用可能で、next/navigationからインポートします。

app/page.js
'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      ダッシュボード
    </button>
  )
}

useRouterの全メソッドについては、APIリファレンスをご覧ください。

推奨事項: 特別な要件がない限り、ルート間のナビゲーションには<Link>コンポーネントを使用してください。

ルーティングとナビゲーションの仕組み

App Routerはルーティングとナビゲーションにハイブリッドアプローチを使用します。サーバー側では、アプリケーションコードがルートセグメントごとに自動的にコード分割されます。クライアント側では、Next.jsがルートセグメントをプリフェッチキャッシュします。つまり、ユーザーが新しいルートに移動する際、ブラウザはページをリロードせず、変更のあるルートセグメントのみが再レンダリングされ、ナビゲーション体験とパフォーマンスが向上します。

1. プリフェッチ

プリフェッチは、ユーザーが訪問する前にルートをバックグラウンドで事前読み込みする方法です。

Next.jsではルートをプリフェッチする方法が2つあります:

  • <Link>コンポーネント: ユーザーのビューポートに表示されると自動的にルートがプリフェッチされます。プリフェッチはページが最初に読み込まれる時やスクロールによって表示された時に発生します。
  • router.prefetch(): useRouterフックを使用してプログラムでルートをプリフェッチできます。

<Link>のプリフェッチ動作は静的ルートと動的ルートで異なります:

  • 静的ルート: prefetchはデフォルトでtrueです。ルート全体がプリフェッチされキャッシュされます。
  • 動的ルート: prefetchはデフォルトで自動です。最初のloading.jsファイルまでの共有レイアウトのみがプリフェッチされ、30秒間キャッシュされます。これにより動的ルート全体を取得するコストが削減され、ユーザーへの視覚的フィードバックを改善する即時ローディング状態を表示できます。

prefetchプロパティをfalseに設定することでプリフェッチを無効化できます。

詳細は<Link> APIリファレンスをご覧ください。

豆知識:

  • プリフェッチは開発環境では有効にならず、本番環境のみで有効です。

2. キャッシュ

Next.jsにはRouter Cacheと呼ばれるインメモリのクライアントサイドキャッシュがあります。ユーザーがアプリ内を移動する際、プリフェッチされたルートセグメントと訪問済みルートのReact Server Componentペイロードがキャッシュに保存されます。

つまり、ナビゲーション時にキャッシュが可能な限り再利用され、サーバーへの新しいリクエストが不要になるため、リクエスト数と転送データ量が削減されパフォーマンスが向上します。

Router Cacheの仕組みと設定方法について詳しく学べます。

3. 部分レンダリング

部分レンダリングとは、ナビゲーション時に変更のあるルートセグメントのみがクライアント側で再レンダリングされ、共有セグメントは保持されることを意味します。

例えば、/dashboard/settings/dashboard/analyticsという兄弟ルート間を移動する場合、settingsanalyticsページがレンダリングされ、共有のdashboardレイアウトは保持されます。

部分レンダリングの仕組み

部分レンダリングがない場合、各ナビゲーションでサーバー側でページ全体が再レンダリングされます。変更のあるセグメントのみをレンダリングすることで、転送データ量と実行時間が削減され、パフォーマンスが向上します。

4. ソフトナビゲーション

デフォルトでは、ブラウザはページ間でハードナビゲーションを実行します。つまり、ブラウザはページをリロードし、アプリ内のuseStateフックなどのReact状態や、ユーザーのスクロール位置やフォーカスされた要素などのブラウザ状態をリセットします。しかし、Next.jsではApp Routerがソフトナビゲーションを使用します。これは、Reactとブラウザの状態を保持しながら、変更のあるセグメントのみをReactがレンダリングし、ページ全体のリロードが発生しないことを意味します。

5. 前後ナビゲーション

デフォルトでは、Next.jsは前後ナビゲーションのスクロール位置を維持し、Router Cache内のルートセグメントを再利用します。