Skip to main content

第113章:「サスペンド(中断)」っていう考え方

ここからいよいよ、React v19 らしい「非同期(データの読み込み)×UI」の世界に入っていきます 🎉

この章ではまだガッツリコードを書くというより、

「サスペンド(suspend)ってそもそも何者? 🧐」

という考え方そのものに集中します。 このイメージが入っていると、このあと出てくる use(Promise)Suspense がめちゃくちゃ理解しやすくなります 💪


🎯 この章のゴール

この章が終わるころには、こんなことが説明できるようになります👇

  • 「サスペンドって、処理を止めるって意味だけど、JavaScript全体が止まるわけじゃないんだよ~」と言える
  • use(Promise)<Suspense> を組み合わせると、『読み込み中画面』と『本当の画面』をいい感じに切り替えてくれる」と説明できる
  • 「サスペンドはエラーじゃなくて、『ちょっと待って!』って合図」というイメージが持てる

1️⃣ まずはイメージ:「レポートを出したいけど、まだデータが来てない」問題 📊📮

Webアプリでよくあるシチュエーションを想像してみてください 👇

  • サイトを開いたら「ユーザー情報」を表示したい
  • でもユーザー情報はサーバーからネット経由で取ってくる
  • ネットからの返事って、すぐ返ってくるとは限らない 😇

つまり、コンポーネント的にはこう言いたい状態です:

「ユーザー情報がないとまともに表示できないんだけど、  今まだ問い合わせ中なんだよね…どうしよ…🤔」

ここで登場するのが、React v19 の

  • use(Promise)(データを読む係)
  • <Suspense>(「待ってる間どうするか」を決める係) (react.dev)

そして、その裏で起きているのが 「サスペンド(中断)」 です。


2️⃣ 「サスペンド」ってどういう状態?🛑=💥ではない!

「サスペンド」って、日本語にすると「中断」ですが、 ここで勘違いしやすいポイントがあります 👇

  • JavaScriptの実行が完全に止まる
  • ブラウザ全体がフリーズする
  • エラーで落ちた状態

ではありません!

React の「サスペンド」は、もっとピンポイントで賢い中断です。

👩‍💻 「このコンポーネント、  まだ必要なデータがそろってないから、  本番のUIを描くのは一旦ストップしとくね。  その代わり、近くの <Suspense> に  『待ち画面』を出してもらうわ~」

みたいな感じの動きです ✨


3️⃣ 旧世界 vs 新世界:どう変わったの?⏲️

🕰 旧世界(v18までのよくあるやり方)

React 18 までは、だいたいこんな流れでデータを取っていました:

  1. まずは「空っぽのUI」または「手作業で作った loading 状態」を表示

  2. useEffect の中で fetch などをしてデータを取得

  3. 結果を useState でセット

  4. loading フラグを見て、

    • 読み込み中なら「読み込み中…」テキストを表示
    • 取れたら本番のUIを表示

つまり、**全部「自分で if 文と state で管理」**してました。(電通総研 テックブログ)


⚡ 新世界(v19 + use + Suspense

React 19 では、こういうイメージに変わります:

  • コンポーネントの中で const user = use(userPromise); みたいにいきなり「完成したデータ」を読むつもりで書く

  • でも中身はまだPromise(未完)なので、Reactが

    「あ、まだ終わってないのね。  じゃあこのコンポーネントはサスペンドしとこ!」

  • 一番近くにある <Suspense>fallback に指定された「読み込み中UI」を表示

  • Promise が解決したら

    「データきたよ~!」 と React が知らせてくれて、 コンポーネントがもう一度レンダリングされて、今度こそ本番UIが出る (tasukehub.com)

つまり、

「読み込み中フラグを自分で管理する」のではなく、  「Promise を渡したら、React & Suspense が待ちと再開をやってくれる」

という世界になります 🌏✨


4️⃣ サスペンドの流れを図で見てみよう 🧠💭

React 19 の use(Promise) + Suspense のざっくりした流れを Mermaid で図解してみます 👇

ポイントはここ 💡

  • 「サスペンド」は、Promise が pending の間だけの一時的な状態
  • 一番近い <Suspense> が「📥 代わりに表示しておく画面(fallback)」を出す
  • Promise が解決したら、サスペンドしていたコンポーネントが「再開」して、本番UIを表示

5️⃣ ミニコードで「サスペンドされてるイメージ」を見る 👀

この章では「概念メイン」ですが、 イメージしやすいように、かなりシンプルにした例を見てみます。

✅ まだ <Suspense> の書き方はちゃんと説明しません ✅ 「サスペンドして、あとで再開するんだな~」ぐらいの雰囲気だけつかめればOK

想像のコード例(ざっくり)

// UserName.tsx
import { use } from "react";

type User = {
id: number;
name: string;
};

// サーバーからユーザー情報を取ってくる Promise(仮)
function fetchUser(userId: number): Promise<User> {
return fetch(`/api/users/${userId}`).then((res) => res.json());
}

type Props = {
userId: number;
};

export function UserName({ userId }: Props) {
// ここで Promise をあえてそのまま use に渡す
const user = use(fetchUser(userId));

// use が返してくれるのは「もう解決済みの値」という前提で書ける✨
return <p>ユーザー名:{user.name}</p>;
}

このコードを読むときの気持ちとしては:

  • user には、「もうサーバーからちゃんと返ってきたデータ」が入っているつもりで書く

  • 実際には、最初のレンダリングでは

    • fetchUser が返した Promise はまだ pending

    • use(promise) を呼んだ瞬間、Reactが

      「あ、まだ終わってないじゃん。  じゃあこのコンポーネントはサスペンドね!」

  • 一番近くの <Suspense>fallback を表示してくれる

という流れになっています。(tasukehub.com)

「Promise の状態(pending / resolved / rejected)を見て、 if (loading) ... みたいに自分で分岐を書かなくていい、 というのがすごく大きなポイントです ✨


6️⃣ サスペンドは「エラー」とどう違うの?🚨 vs ⏸

もうひとつ、よく混ざりがちなポイントです。

  • サスペンド

    • 「まだデータがそろってないから、待っててね~」という一時停止
    • <Suspense>fallback が表示される
  • エラー(Promise が reject された)

    • 「データ取得に失敗しました…😵」という失敗
    • 一番近い「エラーバウンダリ(Error Boundary)」があれば、そっちに切り替わる (react.dev)

サスペンドは「普通の流れの一部」、 エラーは「例外的な状況」

というイメージを持っておくと、 このあと出てくる「エラーバウンダリ」の話(119〜120章)もスムーズに入ってきます 🌈


7️⃣ React から見たサスペンドのメリット 🌟

なぜわざわざ「サスペンド」なんて仕組みを入れるのか?

React 側の視点で見ると、サスペンドにはこんなメリットがあります:

  • 🧼 UIの書き方がシンプルになる

    • loading / error のフラグ管理を毎回自作しなくていい
  • 🧩 コンポーネントを素直に「完成形」で書ける

    • user が「ちゃんとある前提」で JSX を書ける
  • 🧵 複数の非同期処理があっても自然に組み合わせられる

    • <Suspense> をネストして、部分ごとに「読み込み中」を変えられる (react.dev)
  • 🔮 エラー処理との連携もセットで考えられる

    • use + <Suspense> + エラーバウンダリで、 読み込み中・成功・失敗の流れをキレイに分けられる

8️⃣ ミニ確認クイズ 📝✨

頭の中で、サクッと答えてみてください👇

  1. Q. 「サスペンド(suspend)」はエラーと同じ意味?

    • → ❌ ちがう。サスペンドは「まだデータがないから、一旦待機ね〜」という中断状態
  2. Q. コンポーネントがサスペンドしたとき、何が表示される?

    • → 一番近い <Suspense>fallback に指定されたUI が表示される。
  3. Q. use(Promise) を呼んだとき、Promise がまだ pending だったらどうなる?

    • → コンポーネントがサスペンドされ、Promise が解決したあとでもう一度レンダリングされる
  4. Q. サスペンド中、アプリ全体がフリーズする?

    • → ❌ しない。サスペンドしているのはそのコンポーネント(とその子)だけ。他の部分は普通に動く。

9️⃣ この章のまとめ 🎀

最後に、この章のキーワードをギュッとまとめます 💡

  • サスペンド(suspend)

    • 「このコンポーネント、まだ必要なデータがないから一旦ストップね」という状態
  • use(Promise)

    • Promise を渡すと、React が「pending ならサスペンド」「解決したら再開」をよしなにやってくれる
  • <Suspense>

    • サスペンド中に表示する「読み込み中UI(fallback)」を決める場所
  • 大事なイメージ

    • 自分で loading state を管理するのではなく、

      「Promise を React に渡して、  待ち時間のコントロールは React に任せる

次の 第114章 では、 いよいよ <Suspense> を実際に書いてみて、

「サスペンドしている間にどんなUIを見せるか?」

をコードで体験していきます 🚀💻✨

おつかれさまでした~! ☕💕