複数のSuspenseの表示を制御するSuspenseList
React18の実験的機能SuspenseListを使って複数のSuspenseの読み込み順序と表示パターンを制御する方法を解説します。レイアウトシフトの削減とUX向上を実現するコンポーネントです。
SuspenseListは実験中の機能です。今後一部の機能や名前が変更される恐れがあります。
はじめに
2025年の4月23日にReactのブログで実験的な機能としてunstable_ViewTransition
とunstable_Activity
が紹介されました。
これらの新しい実験的機能はとてもパワフルで目が惹かれました。これらの他にあるReactの実験機能も気になりますよね!
ed07719
のコミット時点で他の実験的な機能を探してみると、unstable_LegacyHidden
、unstable_Activity
、unstable_Scope
、unstable_SuspenseList
、unstable_TracingMarker
、unstable_ViewTransition
、unstable_addTransitionType
、unstable_getCacheForType
、unstable_useCacheRefresh
の9種類の機能が提供されていそうでした(参考)。
この記事は、そのうちの一つであるunstable_SuspenseList
の基本的な使い方とその利点について解説します(以後記事ではunstable_SuspenseList
を単にSuspenseList
と呼びます)。
SuspenseListとは
SuspenseList
は、React18で実験的機能として導入されたコンポーネントで、複数のSuspense
の読み込み順序や表示パターンを制御できる機能です。
複数の非同期処理が同時に発生する場面で、UXを向上させるために使用されます。
Add SuspenseList Component by sebmarkbage · Pull Request #15902 · facebook/react · GitHub
This component lets you coordinate the loading sequence of nested Suspense boundaries. How this happens is defined by the revealOrder property. By default, it behaves like a noop so the nested boun...
github.com
基本的な使い方
SuspenseList
はrevealOrder
とtail
のpropsを使用して、子要素の表示順序を制御します。
<SuspenseList revealOrder="forwards" tail="collapsed">
<Suspense fallback={<div>Loading 1...</div>}>
<Component1 />
</Suspense>
<Suspense fallback={<div>Loading 2...</div>}>
<Component2 />
</Suspense>
<Suspense fallback={<div>Loading 3...</div>}>
<Component3 />
</Suspense>
</SuspenseList>
revealOrder
revealOrder
は、子要素の表示順序を制御します。
forwards(順次表示)
子要素を上から順番に表示します。最初の要素が完了するまで、次の要素は表示されません。
<SuspenseList revealOrder="forwards" tail="collapsed">
{/* 1番目が完了してから2番目、2番目が完了してから3番目... */}
</SuspenseList>
backwards(逆順表示)
子要素を下から順番に表示します。最後の要素から逆順で表示されます。
<SuspenseList revealOrder="backwards" tail="hidden">
{/* 最後の要素から逆順で表示 */}
</SuspenseList>
together(同時表示)
すべての子要素が準備できるまで待機し、準備が完了したら一斉に表示します。
<SuspenseList revealOrder="together">
{/* すべて準備完了後に一斉表示 */}
</SuspenseList>
independent(独立表示)
すべての子要素が独立して表示されます。各要素は他の要素の読み込み状態に影響されません。つまり、SuspenseList
が存在しない時と同じ動きをします。
<SuspenseList revealOrder="independent">
{/* 各要素が独立して表示 */}
</SuspenseList>
independent
は執筆当時のReactの最新版19.1では動きません。下の対応が追加されることで利用が可能になります。
Replace Implicit Options on SuspenseList with Explicit Options by sebmarkbage · Pull Request #33424 · facebook/react · GitHub
github.com
この対応に追従する@types/react
側の対応が先に完了しているので、最新の@types/react
を用いている場合はindependent
を付与しても型エラーが発生しないことに注意してください。
React側の変更ではrevealOrder
を渡さなかったときの動作をindependent
という値を渡した時に動くようにして、デフォルト値を渡せないようにしています。
そのため、最新のReactと@types/react
を使用している場合は、independent
相当の動作を起こせないのに注意してください(この動作を実現したい時はSuspenseList
を使う必要がないのですぐに気にする必要はなさそうです)。
tail
tail
は準備前の子要素のフォールバックUIに関する表示を制御します。revealOrder
にforwards
とbackwards
を指定した場合でのみ指定が可能です。
collapsed
次の子要素のフォールバックUIだけを表示します。forwards
であれば最初は1番目の要素のフォールバックUIのみが表示されます。
<SuspenseList revealOrder="forwards" tail="collapsed">
{/* 次のfallbackのみ表示 */}
</SuspenseList>
hidden
すべての子要素のフォールバックUIを非表示にします。
<SuspenseList revealOrder="forwards" tail="hidden">
<Suspense fallback={<div>Loading 1...</div>}>
<Component1 />
</Suspense>
<Suspense fallback={<div>Loading 2...</div>}>
<Component2 />
</Suspense>
</SuspenseList>
visible
すべての子要素のフォールバックUIを表示します。
<SuspenseList revealOrder="forwards" tail="visible">
<Suspense fallback={<div>Loading 1...</div>}>
<Component1 />
</Suspense>
<Suspense fallback={<div>Loading 2...</div>}>
<Component2 />
</Suspense>
</SuspenseList>
この値もrevealOrder
のindependent
と同様に、執筆当時のReactの最新版19.1では動きません。対応を待ちましょう。
SuspenseListの利点
SuspenseList
を使用することで、以下のような利点があります:
- レイアウトシフトの削減: 順次表示されるので、読み込みの順番によるレイアウトの変更を抑制できます。
- UXの向上: ユーザーが期待する順序でコンテンツが表示されるため、体感的な読み込み速度が向上します(子要素のデータの読み込み時間に大きな差がない事を仮定しています)。
Playground
実験的機能なので触った事ない人がほとんどだと思います。以下のPlaygroundでSuspenseList
の世界を実際に体験してください。
SuspenseListのさまざまな利用例
<SuspenseList revealOrder="together">
Cache Key: key1
Time: 1500ms
Cache Key: key2
Time: 2000ms
Cache Key: key3
Time: 500ms
Cache Key: key4
Time: 1000ms
PlaygroundはReactの製品版の最新バージョンで動いています。
まとめ
SuspenseList
は複数の非同期コンポーネントの表示を制御する強力な機能です。適切に使用することで、UXを大幅に向上させることができます。
Reactのブログで紹介されたViewTransition
・addTransitionType
・Activity
、今回紹介したSuspenseList
の他にも実験的な機能は5つもあります。
unstable_LegacyHidden
unstable_Scope
unstable_TracingMarker
unstable_getCacheForType
unstable_useCacheRefresh
興味がある機能があれば触ってみるのはいかがでしょうか。新たな世界を体験できるかもしれません。