複数の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を向上させるために使用されます。
Loading...
Loading...
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では動きません。下の対応が追加されることで利用が可能になります。
Loading...
Loading...
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のさまざまな利用例
React v19.2、Nextjs v16で利用ができなくなったため、現在こちらの機能は利用できません。
<SuspenseList revealOrder="together">
PlaygroundはReactの製品版の最新バージョンで動いています。
おわりに
SuspenseListは複数の非同期コンポーネントの表示を制御する強力な機能です。適切に使用することで、UXを大幅に向上させることができます。
Reactのブログで紹介されたViewTransition・addTransitionType・Activity、今回紹介したSuspenseListの他にも実験的な機能は5つもあります。
unstable_LegacyHiddenunstable_Scopeunstable_TracingMarkerunstable_getCacheForTypeunstable_useCacheRefresh
興味がある機能があれば触ってみるのはいかがでしょうか。新たな世界を体験できるかもしれません。