この章では、Next.jsアプリケーションでデータを取得し、ページに表示する方法について学びます。Next.jsには、静的生成(getStaticProps
)、サーバーサイドレンダリング(getServerSideProps
)、動的ページ生成(getStaticPaths
)など、様々なデータ取得の方法が用意されています。それぞれの特徴と使い分けを理解し、効率的なデータ取得と表示を実装しましょう。
1. getStaticProps
による静的データの取得
getStaticProps
は、ビルド時にデータを取得し、静的なHTMLを生成するために使用します。外部APIやヘッドレスCMSなどからデータを取得して、静的なページを生成するのに適しています。
ビルド時のデータ取得
getStaticProps
は、Next.jsのビルドプロセス中に実行されます。つまり、next build
コマンドを実行したときに、データが取得され、そのデータを使って静的なHTMLが生成されます。
APIからのデータ取得
getStaticProps
を使って、外部APIからデータを取得してみましょう。例として、JSONPlaceholderというダミーAPIを使って、ブログ記事の一覧を取得します。
まず、pages/posts.tsx
を作成し、以下のコードを記述します。
tsx
// pages/posts.tsx
import type { GetStaticProps } from 'next';
interface Post {
id: number;
title: string;
body: string;
}
interface Props {
posts: Post[];
}
const PostsPage: React.FC<Props> = ({ posts }) => {
return (
<div>
<h1>Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>
<h2>{post.title}</h2>
<p>{post.body}</p>
</li>
))}
</ul>
</div>
);
};
export const getStaticProps: GetStaticProps<Props> = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts: Post[] = await res.json();
return {
props: {
posts,
},
};
};
export default PostsPage;
ポイントは、getStaticProps
関数をエクスポートしているところです。この関数は、Next.jsのビルド時に実行され、props
を返します。props
に指定したデータは、ページのコンポーネント(ここではPostsPage
)に渡されます。
取得したデータの表示
PostsPage
コンポーネントでは、getStaticProps
から渡されたposts
データを表示しています。
tsx
const PostsPage: React.FC<Props> = ({ posts }) => {
return (
<div>
<h1>Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>
<h2>{post.title}</h2>
<p>{post.body}</p>
</li>
))}
</ul>
</div>
);
};
posts
配列をmap
メソッドでループ処理し、各記事のタイトルと本文を表示しています。
npm run dev
で開発サーバーを起動し、http://localhost:3000/posts
にアクセスすると、JSONPlaceholder APIから取得した記事の一覧が表示されます。
2. getServerSideProps
によるサーバーサイドレンダリング
getServerSideProps
は、リクエストごとにサーバー側でデータを取得し、ページをレンダリングするために使用します。ユーザーごとに異なるデータを表示する場合や、常に最新のデータを取得する必要がある場合に適しています。
リクエストごとのデータ取得
getServerSideProps
は、ページへのリクエストがあるたびに、サーバー側で実行されます。そのため、常に最新のデータを取得して、ページをレンダリングできます。
ユーザー認証やセッションデータの利用
getServerSideProps
では、リクエストオブジェクトにアクセスできるため、ユーザーの認証情報やセッションデータなどを取得できます。これを利用して、ユーザーごとに異なるデータを表示したり、認証が必要なページを実装したりできます。
例として、リクエストごとにランダムな数字を取得して表示するページを作成してみましょう。pages/random.tsx
を作成し、以下のコードを記述します。
tsx
// pages/random.tsx
import type { GetServerSideProps } from 'next';
interface Props {
randomNumber: number;
}
const RandomPage: React.FC<Props> = ({ randomNumber }) => {
return (
<div>
<h1>Random Number</h1>
<p>The random number is: {randomNumber}</p>
</div>
);
};
export const getServerSideProps: GetServerSideProps<Props> = async () => {
const randomNumber = Math.random();
return {
props: {
randomNumber,
},
};
};
export default RandomPage;
getServerSideProps
関数内で、Math.random()
を使ってランダムな数字を生成し、props
として返しています。このrandomNumber
は、RandomPage
コンポーネントに渡され、ページに表示されます。
http://localhost:3000/random
にアクセスするたびに、異なるランダムな数字が表示されます。
3. getStaticPaths
による動的ページの生成
getStaticPaths
は、getStaticProps
と組み合わせて使用し、動的なパスを持つページを静的に生成するために使用します。例えば、ブログ記事の詳細ページなど、URLにIDなどのパラメータが含まれるページを生成するのに適しています。
動的ルートとデータに基づいたページ生成
getStaticPaths
では、生成するページのパスの一覧を返します。Next.jsは、このパスの一覧に基づいて、静的なHTMLを生成します。
getStaticProps
との組み合わせ
getStaticPaths
は、通常getStaticProps
と組み合わせて使用します。getStaticPaths
でパスの一覧を生成し、getStaticProps
で各パスに対応するデータを取得します。
例として、先ほどのJSONPlaceholder APIを使って、ブログ記事の詳細ページを静的に生成してみましょう。
まず、pages/posts/[id].tsx
を作成し、以下のコードを記述します。
tsx
// pages/posts/[id].tsx
import type { GetStaticProps, GetStaticPaths } from 'next';
interface Post {
id: number;
title: string;
body: string;
}
interface Props {
post: Post;
}
const PostDetailPage: React.FC<Props> = ({ post }) => {
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
};
export const getStaticPaths: GetStaticPaths = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts: Post[] = await res.json();
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return {
paths,
fallback: false, // 存在しないパスには404を返す
};
};
export const getStaticProps: GetStaticProps<Props> = async ({ params }) => {
const id = params?.id;
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
const post: Post = await res.json();
return {
props: {
post,
},
};
};
export default PostDetailPage;
getStaticPaths
では、まずJSONPlaceholder APIから記事の一覧を取得し、paths
配列を生成しています。paths
配列には、生成するページのパスの一覧が含まれます。ここでは、各記事のIDをパスパラメータとして指定しています。
fallback: false
は、paths
で指定されていないパスにアクセスがあった場合に、404ページを表示する設定です。
getStaticProps
では、params
オブジェクトからid
を取得し、そのIDに対応する記事データを取得しています。取得したデータは、props
としてPostDetailPage
コンポーネントに渡されます。
http://localhost:3000/posts/1
などにアクセスすると、対応する記事の詳細ページが表示されます。