11
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Next.jsのダイナミックルーティングを実装してみた

Next.jsでは、getStaticPaths・getStaticProps・getServerSidePropsといった似た名前の関数が多く違いがわかりづらいですよね...

今回は、その中でも使用頻度の高いgetStaticPaths・getStaticPropsを使用し、ダイナミックルーティングの簡単なサンプルを作成したいと思います。

こちらが今回作成するサンプルの完成形です。
画面収録-2020-10-15-17.32.51.gif
URL:https://nextjs-dynamic.vercel.app/

JSONPlaceholderのAPIサーバーを使用し、記事一覧・記事詳細ページを表示しています。
見ての通り、全てのデータが事前ビルドされているため表示が高速です。

では、実装までの流れについて説明していきます。

1. ダイナミックルート用のファイル作成

まずは、ダイナミックルート用のファイル(記事詳細ページ)を作成します。
Next.jsでは、pages内でファイル名に[]を使用することで自動的にダイナミックルート対象となります。

 /pages/[id].js                               
   ├ http://localhost:3000/1
   ├ http://localhost:3000/2
   └ ...

ダイナミックルート用のファイルでは、getStaticPathsgetStaticPropsの関数が必要です。

getStaticPaths:ビルド時にレンダリングする必要のあるパスのリストを生成する
getStaticProps:ビルド時に静的なファイルを生成し、ページコンポーネントで使用する値を用意する

これらの関数はクライアント側で実行されることはなく、必ずサーバーサイドで実行されます。

以下は作成した記事詳細ページです。

pages/[id].js
import Link from 'next/link'

// post:getStaticPropsから取得したデータ
export default ({ post }) => {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <Link href="/">
        <a>Back</a>
      </Link>
    </div>
  )
}

export const getStaticPaths = async () => {
  // 外部APIエンドポイントを呼び出しデータ取得
  const res = await fetch("https://jsonplaceholder.typicode.com/posts")
  const posts = await res.json()  

  // 事前ビルドしたいパスを指定
  const paths = posts.map((post) => ({
    params: {
      // ファイル名と合わせる ※文字列指定
      id: post.id.toString(),
    },
  }))
  // paths:事前ビルドするパス対象を指定するパラメータ
  // fallback:事前ビルドしたパス以外にアクセスしたときのパラメータ true:カスタム404Pageを表示 false:404pageを表示
  return { paths, fallback: false }
}

// paramsには上記pathsで指定した値が入る(1postずつ)
export const getStaticProps = async ({ params }) => {  
  // 外部APIエンドポイントを呼び出しデータ取得
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`)
  const post = await res.json()  

  // ページコンポーネントにpropsとしてに渡す
  return {
    props: {
      post
    },
  }
}

画面表示までの流れ

  1. getStaticPathsで、レンダリングする必要のあるパスのリストを生成する
  2. getStaticPropsで、1で生成したパスのリストから1postsずつAPIエンドポイントを呼び出しデータを取得する
  3. ページコンポーネントがgetStaticPropsからデータを受け取り、画面に表示される

実際にURLにアクセスしてみると、表示が切り替わることが確認できるかと思います。

画面収録-2020-10-15-16.30.12.gif

2. 記事一覧ページ作成

次に、それぞれの詳細ページにリンクする記事一覧を作成します。

こちらのページに関しても、getStaticPropsでページコンポーネントで使用する値を事前に用意する必要があります。

以下は作成した記事一覧ページです。

pages/index.js
import Link from 'next/link'

// posts:getStaticPropsで取得したデータを受け取る
const Home = ({ posts }) => {
  return (
    <div>
      <h1>記事一覧</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            {/* リンク先を指定 */}
            <Link href={`/${post.id}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

// ビルド時にデータを取得し静的なファイルを事前に生成
export const getStaticProps = async () => {
  // 全記事データを取得
  const res = await fetch("https://jsonplaceholder.typicode.com/posts")
  const posts = await res.json()  

  // コンポーネントに渡すデータを指定
  return {
    props: {
      posts,
    },
  }
}

export default Home

画面表示までの流れ

  1. getStaticPropsで、画面表示させたいデータを取得する
  2. ページコンポーネントがgetStaticPropsからデータを受け取り、画面に表示される

以上でダイナミックルーティングの実装完了になります!

おわりに

Next.js公式がSSGを推薦していることもあり、今後さらにダイナミックルーティングを使用する機会が増えていきそうですね!

公式チュートリアルでは、実際にブログを作成しながらダイナミックルーティングについて学ぶことができるので、より詳しく知りたいという方はぜひお試し下さい!
Next.js Dynamic Routes

参考資料

Next.js 公式ドキュメント
Next.js 9.3 Released, Improves Static Site Generation
JSONPlaceholder

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
11
Help us understand the problem. What are the problem?