React Suspense

リアクト サスペンス

React Suspense を分かりやすく

React Suspenseについて話しましょうね。これはReactが提供する強力な機能で、非同期のデータ取得を扱う時のUXを向上させるものです。

ここでの「非同期」は、例えばAPIからデータを取得するときなど、何かを待つ必要がある処理を指します。React Suspenseはこの「待つ」部分をよりスマートに管理し、その間に表示するコンテンツをより柔軟に制御できるようにします。

さて、これを例え話で説明してみましょう。React Suspenseを、一つのレストランと考えてみてください。お客さんが注文をしたとき、その料理が出来上がるまで待つ時間がありますよね。この「待つ時間」がまさに「非同期」な処理なんです。そして、その待つ時間に何をするかが大事ですよね。

一体ナンノコッチャ?って思いますよね?でも、ちょっと待ってみてください。ここでレストランのウェイトレスがスマートに行動します。彼女はお客さんにパンを提供したり、飲み物を持ってきたりします。これは待ち時間を有効に使い、お客さんが飽きさせないための工夫です。

React Suspenseもまさに同じ役割を果たします。データが読み込まれるまでの間、一部のコンポーネント(例えばローディングインジケーターなど)を表示してユーザーに待つことを伝えます。これにより、ユーザーは何も表示されない時間を過ごすことなく、より良いUXを体験できるのです。

React Suspense、凄くないですか?これでユーザーが「何も起こらない...」と感じる時間を減らすことができます。それこそがReact Suspenseのすごいところなんですよ。ここまで大丈夫ですか?

結論

React Suspenseは、非同期データ処理に関連するReactアプリケーションの開発を容易にするための新機能です。これは、特に外部のRESTサービスなど非同期データソースとやり取りするReactアプリで役立ちます。Suspenseを利用することで、アプリケーションのプログラミングが容易になるだけでなく、ユーザーに対するパフォーマンスも大幅に向上します。

React Suspense の歴史的変遷

React SuspenseはReact 18、別名 Concurrent Reactに初めて導入されました。これは新たな並行レンダリングエンジンの一部として機能し、ReactがWebページ上で何をレンダリングするかを決定する方法に根本的な変更をもたらしました。

React Suspense と Jamstack の関係

React Suspenseは、JamstackアーキテクチャにおけるReactの一部として機能します。Jamstackは、JavaScript、API、Markup(マークアップ)の3つの主要な要素からなるモダンなWeb開発のアーキテクチャです。ReactはそのJavaScriptの部分を担当し、SuspenseはReactアプリケーションが非同期データソースとやり取りする際のユーザーエクスペリエンスを向上させる役割を果たします。

React Suspense を使うメリット

シンプルなコードになる

React Suspenseを使用すると、データのレンダリングに関連するコードが大幅に簡素化されます。従来は、各コンポーネントのローディング状態の追跡が必要でしたが、Suspenseを使用すると、その必要がなくなります。

最適なレンダリング

Reactの新しい並行レンダリングエンジンにより、React Suspenseはデータが最初に到着したものからページを再レンダリングすることができます。

React 18が提供する新機能の一つであるSuspenseは、新しい並行レンダリングエンジンを利用しており、よりレスポンシブなUIを少ないブラウザリソースを使って構築することを可能にしています。また、Suspenseを用いると、データフェッチの状態(ローディングやエラー)を追跡する必要がなくなり、コンポーネントの宣言型プログラミングがより容易になります。

ただし、現時点では、React 18の並行レンダリングとSuspenseをフルに活用するためには、Relayというデータ取得APIを使用する必要があります。その他のデータアクセスライブラリ(SWR、React-Query、ApolloGraphQLなど)を使用している開発者は現在、Suspenseを利用することはできませんが、Reactチームは将来的にはSuspenseをRelay以外のAPIでも動作するようにすると明言しています。

実装例

Jamstack(JavaScript、API、Markup)は、前端開発でよく使用されるアーキテクチャで、静的サイトジェネレータ、サーバーレス機能、クライアントサイドJavaScriptなどを活用しています。ReactはJavaScriptライブラリであり、Jamstackアーキテクチャに適しています。

以下に、React 18とSuspenseを使用してJamstackアプリケーションを作る簡単な例を示します。この例では、外部APIからデータを非同期に取得し、そのデータを表示するReactコンポーネントを作成します。

import React, { Suspense } from 'react';
import { createResource } from './createResource';
// これはあなたが自分で実装するか、適切なライブラリを使用する必要があります

// APIからデータを取得するためのリソースを作成します
const myDataResource = createResource(() => 
  fetch('https://api.example.com/data')
    .then(response => response.json())
);

// データを表示するコンポーネント
const DataComponent = () => {
  const data = myDataResource.read();
  // データが利用可能になるまで、このコンポーネントはレンダリングを「停止」します

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.description}</p>
    </div>
  );
};

// アプリケーションのメインコンポーネント
const App = () => (
  <div>
    <Suspense fallback={<div>Loading...</div>}>
      <DataComponent />
    </Suspense>
  </div>
);

export default App;

この例では、createResource関数がAPIからデータを非同期に取得します。これはあなたが自分で実装するか、適切なライブラリを使用する必要があります。APIからのデータ取得はプロミスベースで行われ、その結果はmyDataResourceに格納されます。このリソースは、データを表示するDataComponent内で読み込まれます。

ReactのSuspenseは、DataComponentがレンダリングされるときに、myDataResource.read()が即時にデータを返すか(つまり、データがすでに取得されている場合)、プロミスを返すか(つまり、データの取得がまだ完了していない場合)を見ています。後者の場合、Suspenseはそのコンポーネントのレンダリングを「一時停止」し、代わりにfallbackプロップで指定されたコンテンツ(この例では<div>Loading...</div>)を表示します。

現時点では、Suspenseは非同期データの読み込みに対して完全に対応しているわけではなく、Facebookが開発したRelayというデータフェッチライブラリと組み合わせて使用することが推奨されています。他のデータアクセスライブラリ(例えばSWR、React-Query、ApolloGraphQLなど)とSuspenseを組み合わせて使用する場合は、それらがSuspenseに対応しているかどうかを確認する必要があります。