はじめに
以下の記事では、Pages Router のレンダリング実装方法について記載しました。
今回は App Router のレンダリング実装方法について記載していきます。
開発環境
開発環境は以下の通りです。
- Windows11
- VSCode
- Next.js 13.4.7
- React 18.2.0
- TypeScript 5.1.3
プロジェクト作成
まずは以下のコマンドを実行して、プロジェクトを作成します。
npx create-next-app@latest
インストール中にプロンプトが表示されます。No / Yes はすべてデフォルト値を選択します。
インストールが完了するとプロジェクトファイルが作成されます。
Client 側でのレンダリング
App Router では、Server Component と Client Component というようにコンポーネント単位でレンダリングの種類を選択できるようになりました。デフォルトでは、Server Component が利用されます。そのため、Client Component を利用するときは、"use client"
とファイルに記載する必要があります。
例えば、SWR を利用してクライアント側で、データを取得したい場合、以下のように記載します。
"use client";
import { SAMPLE_API_ENDPOINT } from "@/api";
import { FetchedRandomJoke } from "@/components/FetchedRandomJoke";
import { RandomJoke } from "@/types";
import Head from "next/head";
import useSWR from "swr";
export const TITLE = "Client-Side Rendering (CSR)";
export default function ClientSideRendering() {
const { data: randomJoke } = useSWR<RandomJoke>(SAMPLE_API_ENDPOINT, fetcher);
return (
<>
<Head>
<title>{TITLE}</title>
</Head>
<h1>{TITLE}</h1>
<p>Data fetched on the client-side only.</p>
<FetchedRandomJoke randomJoke={randomJoke} />
</>
);
}
async function fetcher() {
const response = await fetch(SAMPLE_API_ENDPOINT);
const randomJoke = await response.json();
return randomJoke;
}
Dynamic Data Fetching
サーバー側でレンダリング(データ取得)する手法として、Dynamic Data Fetching と Static Data Fetching の2種類あります。
Dynamic Data Fetching を利用する場合、fetch の第二引数に await fetch(SAMPLE_API_ENDPOINT, { cache: "no-store" });
を追加します。
import Head from "next/head";
import { RandomJoke } from "@/types";
import { SAMPLE_API_ENDPOINT } from "@/api";
import { FetchedRandomJoke } from "@/components/FetchedRandomJoke";
export const TITLE = "Dynamic Data Fetching";
export default async function DynamicDataFetching() {
const randomJoke = await getRandomJoke();
return (
<>
<Head>
<title>{TITLE}</title>
</Head>
<h1>{TITLE}</h1>
<p>
Data fetched on the server-side at <b>each</b> request before sending to
the client.
</p>
<FetchedRandomJoke randomJoke={randomJoke} />
</>
);
}
export async function getRandomJoke(): Promise<RandomJoke> {
const response = await fetch(SAMPLE_API_ENDPOINT, { cache: "no-store" });
const randomJoke = await response.json();
return randomJoke;
}
Static Data Fetching
Static Data Fetching を利用する場合、fetch の第二引数には何も加える必要はありません。
import Head from "next/head";
import { RandomJoke } from "@/types";
import { SAMPLE_API_ENDPOINT } from "@/api";
import { FetchedRandomJoke } from "@/components/FetchedRandomJoke";
export const TITLE = "Static Data Fetching";
export default async function StaticDataFetching() {
const randomJoke = await getRandomJoke();
return (
<>
<Head>
<title>{TITLE}</title>
</Head>
<h1>{TITLE}</h1>
<p>
Data fetched at <b>build-time</b> on the server-side before sending to
the client.
</p>
<FetchedRandomJoke randomJoke={randomJoke} />
</>
);
}
export async function getRandomJoke(): Promise<RandomJoke> {
const response = await fetch(SAMPLE_API_ENDPOINT);
const randomJoke = await response.json();
return randomJoke;
}
fetch の第二引数を { next: { revalidate: 10 } }
のようにすると、データを再取得する間隔を指定することができます。