Menu

リンクとナビゲーション

Next.jsのルーターを使用すると、シングルページアプリケーションと同様に、ページ間でクライアント側のルート遷移を実行できます。

このクライアント側のルート遷移を行うために、LinkというReactコンポーネントが提供されています。

import Link from 'next/link'
 
function Home() {
  return (
    <ul>
      <li>
        <Link href="/">Home</Link>
      </li>
      <li>
        <Link href="/about">About Us</Link>
      </li>
      <li>
        <Link href="/blog/hello-world">Blog Post</Link>
      </li>
    </ul>
  )
}
 
export default Home

上記の例では複数のリンクを使用しています。それぞれがパス(href)を既知のページにマッピングしています。

  • /pages/index.js
  • /aboutpages/about.js
  • /blog/hello-worldpages/blog/[slug].js

ビューポート内のあらゆる<Link />(初期状態またはスクロール経由)は、デフォルトでプリフェッチされます(対応するデータを含む)。これは静的生成を使用するページに対して適用されます。サーバーレンダリングルートの対応するデータは、<Link />がクリックされた場合のみフェッチされます。

動的パスへのリンク

パスを作成するために補間を使用することもできます。これは動的ルートセグメントに便利です。例えば、コンポーネントにプロップとして渡されたポストのリストを表示する場合です。

import Link from 'next/link'
 
function Posts({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link href={`/blog/${encodeURIComponent(post.slug)}`}>
            {post.title}
          </Link>
        </li>
      ))}
    </ul>
  )
}
 
export default Posts

encodeURIComponentは、この例でパスをutf-8互換に保つために使用されます。

別の方法として、URLオブジェクトを使用することもできます。

import Link from 'next/link'
 
function Posts({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link
            href={{
              pathname: '/blog/[slug]',
              query: { slug: post.slug },
            }}
          >
            {post.title}
          </Link>
        </li>
      ))}
    </ul>
  )
}
 
export default Posts

パスを作成するために補間を使用する代わりに、href内のURLオブジェクトを使用します。ここで、

  • pathnamepagesディレクトリ内のページの名前です。この場合は/blog/[slug]です。
  • queryは動的セグメントを含むオブジェクトです。この場合はslugです。

ルーターのインジェクション

Reactコンポーネント内でrouterオブジェクトにアクセスするには、useRouterまたはwithRouterを使用できます。

一般的にはuseRouterの使用をお勧めします。

命令型ルーティング

next/linkはほとんどのルーティングのニーズをカバーできますが、それなしにクライアント側のナビゲーションを行うこともできます。next/routerのドキュメントをご覧ください。

以下の例では、useRouterを使用して基本的なページナビゲーションを実行する方法を示しています。

import { useRouter } from 'next/router'
 
export default function ReadMore() {
  const router = useRouter()
 
  return (
    <button onClick={() => router.push('/about')}>
      Click here to read more
    </button>
  )
}

シャロールーティング

Examples

シャロールーティングでは、データフェッチングメソッドを再度実行することなくURLを変更できます。これにはgetServerSidePropsgetStaticProps、およびgetInitialPropsが含まれます。

routerオブジェクトuseRouterまたはwithRouterによって追加)経由で更新されたpathnamequeryを受け取ります。状態を失うことはありません。

シャロールーティングを有効にするには、shallowオプションをtrueに設定します。以下の例を考えてみます。

import { useEffect } from 'react'
import { useRouter } from 'next/router'
 
// 現在のURLは'/'です
function Page() {
  const router = useRouter()
 
  useEffect(() => {
    // 常に最初のレンダー後にナビゲーションを実行します
    router.push('/?counter=10', undefined, { shallow: true })
  }, [])
 
  useEffect(() => {
    // カウンターが変更されました!
  }, [router.query.counter])
}
 
export default Page

URLは/?counter=10に更新され、ページは置き換えられず、ルートの状態のみが変更されます。

以下に示すように、componentDidUpdate経由でURLの変更を監視することもできます。

componentDidUpdate(prevProps) {
  const { pathname, query } = this.props.router
  // 無限ループを避けるため、プロップが変更されたことを確認します
  if (query.counter !== prevProps.router.query.counter) {
    // 新しいクエリに基づいてデータをフェッチします
  }
}

注意事項

シャロールーティングは、現在のページ内のURL変更にのみ機能します。例えば、pages/about.jsという別のページがあると仮定して、以下を実行する場合です。

router.push('/?counter=10', '/about?counter=10', { shallow: true })

これは新しいページなので、現在のページがアンロードされ、新しいページが読み込まれ、シャロールーティングを実行するよう指示した場合でも、データフェッチングを待機します。

シャロールーティングがプロキシと一緒に使用される場合、新しいページが現在のページと一致することを保証しません。これは以前にプロキシなしで実行されていました。これはプロキシが動的に書き換えることができ、シャローでスキップされるデータフェッチなしにクライアント側で検証することができないためです。そのため、シャロールート変更は常にシャローとして扱われる必要があります。