Chapter 02

Suspenseはどのような機能なのか

uhyo
uhyo
2021.12.28に更新
このチャプターの目次

Suspenseがどのような機能なのかについては、以前に以下の記事で解説したので、これを参照するのがよいでしょう。

https://qiita.com/uhyo/items/bbc22022fe846fd2b763

しかし、せっかくなのでこの本でも簡単に解説しておきます。

Suspenseの概要

一言でいえば、コンポーネントを「ローディング中なのでまだレンダリングできない」という状態にすることができるのが特徴です。ReactはコンポーネントをレンダリングしてDOM(など)に反映することが役割のライブラリなので、ローディングできないコンポーネントがあるということはレンダリング結果が無くてDOMへの反映もできないということになってしまいます。

そこで、Suspenseというコンポーネントが、内部でレンダリングが失敗したコンポーネントのハンドリングを担当してくれます。これはまるでJavaScriptのtry-catch文のようです(実際、Suspenseの機構と、Reactの既存機能であるErrorBoundaryの機構はとても似ています)。

SuspenseのAPI

SuspenseのAPIは主に2つの部分からなります。一つはコンポーネントが「ローディング中」を宣言する部分です。それは、コンポーネントがレンダリング中(関数コンポーネントの関数本体を実行中)にPromiseをthrowすることで行います。Promiseについては解説するまでもないとは思いますが、これは非同期処理を表すオブジェクトで、非同期処理終了後に解決 (settle) するのが特徴です。コンポーネントがPromiseをthrowすることは、「このPromiseが解決するまではコンポーネントをレンダリングできない」という意味になります。なお、コンポーネントがPromiseをthrowした場合、そのコンポーネントはサスペンドしたと言います。

もう一つの部分はSuspenseコンポーネントです。このコンポーネントで囲った部分でサスペンドが発生した場合、あらかじめ指定してあったフォールバックコンテンツが代わりにレンダリングされます。次の例は、MyComponentをレンダリングするが、レンダリングできなかった(サスペンドした)場合はfallbackを代わりにレンダリングするという意味になっています。

<Suspense fallback={<div>サスペンドしたらこれが表示される</div>}>
  {/* ↓サスペンドしなかったらこれが表示される */}
  <MyComponent />
</Suspense>

Suspenseの骨子はたったこれだけです。これだけで非同期処理をうまく宣言的に書けるようになるのが驚きですね。

とはいえ、これらのAPIはローレベルです。つまり、便利さはさておき必要最低限のAPIのみが定義されており、その上に便利なAPIを構築するのはサードパーティに任せるというやり方です。だからこそ、Suspenseコンポーネントはさておき、実際のところ我々が書くアプリケーションコードでPromiseをthrowすることはほとんど無いでしょう。Promiseをthrowするなんて気持ち悪いという意見もよく見られますが、気持ち悪かったとしてもその点は普通ライブラリに隠蔽されるので、皆さんが心配する必要は無いということですね。

しかし、本書は生のSuspenseを体験するというコンセプトなので、次章からはどんどんPromiseをthrowしていきます。