コンテンツにスキップ

リンクとナビゲーション

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>
  )
}

シャロールーティング

シャロールーティングは、getServerSidePropsgetStaticPropsgetInitialProps を含むデータ取得メソッドを再度実行することなく、URL を変更できます。

(useRouter または withRouter によって追加された) router オブジェクト を介して、状態を失うことなく、更新された pathnamequery を受け取ります。

シャロールーティングを有効にするには、shallow オプションを true に設定します。次の例を検討してください。

import { useEffect } from 'react'
import { useRouter } from 'next/router'
 
// Current URL is '/'
function Page() {
  const router = useRouter()
 
  useEffect(() => {
    // Always do navigations after the first render
    router.push('/?counter=10', undefined, { shallow: true })
  }, [])
 
  useEffect(() => {
    // The counter changed!
  }, [router.query.counter])
}
 
export default Page

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

URL の変更は componentDidUpdate を介して監視することもできます。以下に示します。

componentDidUpdate(prevProps) {
  const { pathname, query } = this.props.router
  // verify props have changed to avoid an infinite loop
  if (query.counter !== prevProps.router.query.counter) {
    // fetch data based on the new query
  }
}

注意点

シャロールーティングは、現在のページでの URL 変更にのみ機能します。たとえば、pages/about.js という別のページがあり、次のように実行するとします。

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

これは新しいページであるため、現在のページはアンロードされ、新しいページがロードされ、シャロールーティングを要求したにもかかわらず、データ取得が待機されます。

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