Next.jsでは、getStaticPaths・getStaticProps・getServerSidePropsといった似た名前の関数が多く違いがわかりづらいですよね...
今回は、その中でも使用頻度の高いgetStaticPaths・getStaticPropsを使用し、ダイナミックルーティングの簡単なサンプルを作成したいと思います。
こちらが今回作成するサンプルの完成形です。
URL:https://nextjs-dynamic.vercel.app/
JSONPlaceholderのAPIサーバーを使用し、記事一覧・記事詳細ページを表示しています。
見ての通り、全てのデータが事前ビルドされているため表示が高速です。
では、実装までの流れについて説明していきます。
#1. ダイナミックルート用のファイル作成
まずは、ダイナミックルート用のファイル(記事詳細ページ)を作成します。
Next.jsでは、pages内でファイル名に[]
を使用することで自動的にダイナミックルート対象となります。
/pages/[id].js
├ http://localhost:3000/1
├ http://localhost:3000/2
└ ...
ダイナミックルート用のファイルでは、getStaticPaths
とgetStaticProps
の関数が必要です。
getStaticPaths:ビルド時にレンダリングする必要のあるパスのリストを生成する
getStaticProps:ビルド時に静的なファイルを生成し、ページコンポーネントで使用する値を用意する
これらの関数はクライアント側で実行されることはなく、必ずサーバーサイドで実行されます。
以下は作成した記事詳細ページです。
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
},
}
}
###画面表示までの流れ
- getStaticPathsで、レンダリングする必要のあるパスのリストを生成する
- getStaticPropsで、1で生成したパスのリストから1postsずつAPIエンドポイントを呼び出しデータを取得する
- ページコンポーネントがgetStaticPropsからデータを受け取り、画面に表示される
実際にURLにアクセスしてみると、表示が切り替わることが確認できるかと思います。
#2. 記事一覧ページ作成
次に、それぞれの詳細ページにリンクする記事一覧を作成します。
こちらのページに関しても、getStaticProps
でページコンポーネントで使用する値を事前に用意する必要があります。
以下は作成した記事一覧ページです。
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
###画面表示までの流れ
- getStaticPropsで、画面表示させたいデータを取得する
- ページコンポーネントがgetStaticPropsからデータを受け取り、画面に表示される
以上でダイナミックルーティングの実装完了になります!
#おわりに
Next.js公式がSSGを推薦していることもあり、今後さらにダイナミックルーティングを使用する機会が増えていきそうですね!
公式チュートリアルでは、実際にブログを作成しながらダイナミックルーティングについて学ぶことができるので、より詳しく知りたいという方はぜひお試し下さい!
Next.js Dynamic Routes
#参考資料
Next.js 公式ドキュメント
Next.js 9.3 Released, Improves Static Site Generation
JSONPlaceholder