メインコンテンツまでスキップ

Suspense

前の章では、loading.tsxを使ってデータ取得中に表示する画面を作成しました。時には画面全体のローディング状態だけではなく、コンポーネントごとにローディング状態を表現したい場合もあります。そのような場合には、Suspenseを使うことで簡単に実装することができます。

Suspense

Suspenseは、React 18 から導入された新しい機能です。Suspenseを使うことで、非同期処理中にローディング画面を表示することができます。

Suspenseを使うには、React.Suspenseコンポーネントを使います。React.Suspenseコンポーネントの中に、非同期処理を行うコンポーネントをラップします。

まずは、src/app/profile/settings/page.tsxで犬の画像の部分をコンポーネント化したいので、profileディレクトリの下に_componentsディレクトリを作成し、dogPicture.tsxというファイルを作成します。

そして、dogPicture.tsxに以下のコードを追加してください。

src/app/profile/settings/_components/dogPicture.tsx
type DogPicture = {
message: string;
status: string;
};

async function getData(): Promise<DogPicture> {
const res = await fetch("https://dog.ceo/api/breeds/image/random", {
cache: "no-cache",
});

return res.json();
}

export default async function DogPicture() {
const data = await getData();

return <img src={data.message} alt="犬の画像" />;
}

次に、page.tsxDogPictureコンポーネントを使うように変更します。

src/app/profile/settings/page.tsx
import DogPicture from "@/app/profile/_components/dogPicture";

export default function Settings() {
return (
<div>
<h1>設定ページ</h1>
<DogPicture />
</div>
);
}

そして、Suspense を import して、コンポーネントをラップします。

src/app/profile/settings/page.tsx
import DogPicture from "@/app/profile/_components/dogPicture";
import { Suspense } from "react";

export default function Settings() {
return (
<div>
<h1>設定ページ</h1>
<Suspense fallback={<div>ロード中...</div>}>
<DogPicture />
</Suspense>
</div>
);
}

fallback には、非同期処理中に表示するコンポーネントを指定します。ここでは、divタグでロード中...と表示するようにしています。

http://localhost:3000/profile/settings にアクセスすると、犬の画像が表示される前にロード中...と表示されていることが確認できます。

実際にはローディングスケルトンなどの、より洗練された表現を使うと良いでしょう。