第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 までは、だいたいこんな流れでデータを取っていました:
-
まずは「空っぽのUI」または「手作業で作った
loading状態」を表示 -
useEffectの中でfetchなどをしてデータを取得 -
結果を
useStateでセット -
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️⃣ ミニ確認クイズ 📝✨
頭の中で、サクッと答えてみてください👇
-
Q. 「サスペンド(suspend)」はエラーと同じ意味?
- → ❌ ちがう。サスペンドは「まだデータがないから、一旦待機ね〜」という中断状態。
-
Q. コンポーネントがサスペンドしたとき、何が表示される?
- → 一番近い
<Suspense>のfallbackに指定されたUI が表示される。
- → 一番近い
-
Q.
use(Promise)を呼んだとき、Promise がまだpendingだったらどうなる?- → コンポーネントがサスペンドされ、Promise が解決したあとでもう一度レンダリングされる。
-
Q. サスペンド中、アプリ全体がフリーズする?
- → ❌ しない。サスペンドしているのはそのコンポーネント(とその子)だけ。他の部分は普通に動く。
9️⃣ この章のまとめ 🎀
最後に、この章のキーワードをギュッとまとめます 💡
-
サスペンド(suspend)
- 「このコンポーネント、まだ必要なデータがないから一旦ストップね」という状態
-
use(Promise)- Promise を渡すと、React が「pending ならサスペンド」「解決したら再開」をよしなにやってくれる
-
<Suspense>- サスペンド中に表示する「読み込み中UI(fallback)」を決める場所
-
大事なイメージ
-
自分で
loadingstate を管理するのではなく、「Promise を React に渡して、 待ち時間のコントロールは React に任せる」
-
次の 第114章 では、
いよいよ <Suspense> を実際に書いてみて、
「サスペンドしている間にどんなUIを見せるか?」
をコードで体験していきます 🚀💻✨
おつかれさまでした~! ☕💕