FrontEnd

React QueryのSuspese Modeを使ってみた! [TypeScript]

投稿日:

はじめに

React 18が先日正式リリースされましたね🎉 その中でも、Suspense機能が気になったので調べていたところ、React QueryがSuspenseモードをサポートしていたため、調査して記事にまとめました。

React Suspenseとは

Suspenseとは、データ取得するときのローディング状態を表現できるコンポーネントで、次のような使い方をします。

Issuesはクエリを実行するコンポーネントですが、ローディング中はPromiseがthrowされることによってサスペンド状態となり、代わりにfallbackに指定した内容がレンダリングされる仕組みです。
コンポーネントがサスペンド状態になると、レンダリング自体が行われなくなるため、レンダリングコストの軽減にもつながりそうですね。

ちなみに、Suspense自体はReact 16.6で実験的機能として追加され、React Queryも以前からサポートされていたようですが、React 18で正式版となったことで、使いたい場面が増えてくるかもしれません!

React Queryでは、Suspenseモードを有効化することで、実装できるようになります。Suspenseモードを使わない場合では、useQuery() から data, isLoading, error を取得し、isLoadingやerrorの内容をみてコンポーネントの中身を出し分けるという実装が多かったと思います。
Suspenseモードを使う場合は、ローディング中はPromiseがthrowされ、エラーの場合はJSエラーがthrowされるため、これらの状態によってコンポーネントの中身を出し分ける必要がなくなります。
その代わりに、親コンポーネントでのハンドリングが必要となり、ローディング中はSuspenseコンポーネント、エラーはErrorBoundaryを使って実装します。
それでは、ここからは実装方法を紹介します。

React QueryのSuspense Mode

今回は、React QueryのSuspense Modeを使った実装方法を紹介します。全体のコードはこちらのCodeSandBoxで動かせるようになっています!

事前準備

React Queryのhookを実装します。今回は、Github APIのIssuesを取得するAPIをリクエストするようにしています。

Suspenseモードの有効化

React Queryでは、hook単位でSuepenseモードを有効化する方法と、全体で有効化する方法があります。今回は全体で有効化する方法で実装してみます。
QueryClientの生成時のオプションとして、 suspense: true を設定することでSuspenseモードを有効化できます。

データをフェッチするコンポーネントの実装

GithubのIssueを取得して表示するコンポーネントを実装します。

この実装のポイントとしてはReact QueryでSuspenseモードを有効化すると、 isLoadingerror の面倒を見る必要がなくなります。その代わりにローディング中は、Promiseがthrowされるようになるため、このIssuesコンポーネントをサスペンド状態となり、レンダリングされなくなります。
エラーが発生した場合は、親コンポーネントにエラーがthrowされるため、ErrorBoundaryでキャッチする必要があります。

ErrorBoundaryの実装

続いて、ErrorBoundaryを実装します。

このErrorBoundaryは、エラーが発生したときに、クエリを再試行する仕組みを実装しました。この仕組みを紹介します。
Propsで reset: () => void を受け取るようにしています。これは、後ほど実装する親コンポーネントの QueryErrorResetBoundary から受け取れる関数がそのまま入るようになっいます。
この reset() 関数は、子コンポーネントで実行された直近のクエリをリセットし、再試行させることができます。

Suspenseの実装

ここからは、Suspenseコンポーネントを使って実装します。

親から順に QueryErrorResetBoundary > ErrorBoundary > Suspense > Issues(クエリを実行するコンポーネント) という親子関係になっている点がポイントです。これらのコンポーネントが実際に動作する流れを説明します。

  • Issuesコンポーネントがローディング中の場合、サスペンドするため、そのfallbackである <h1>loading...</h1> が表示されます。
  • ローディングが完了すると、Issuesコンポーネントがレンダリングされます。
  • エラーが発生した場合は、ErrorBoundaryコンポーネントでキャッチします。
  • QueryErrorResetBoundaryを使うと、エラー発生時に reset() を呼び出すことで、クエリを再試行できます。

おまけ

せっかくローディング状態を実装するので、MUIのSkeltonを使ったUIも作ってみました。

さいごに

React QueryのSuspenseモードを使うと、これまでは各コンポーネントでハンドリングしていた状態を、親コンポーネントに集約することができ、実装がスッキリすることが分かりました。各コンポーネントで同じようなハンドリングを実装している場合は、Suspenseモードの方が効率よく実装できるかもしれませんね!

おすすめ書籍

Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

blog-page_footer_336




blog-page_footer_336




-FrontEnd
-, ,

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

js

WebページにGoogleMapを配置する

1 はじめに2 準備2.1 API Keyを取得する3 簡単な実装3.1 サンプルコード4 タップした位置にマーカを動かす4.1 サンプルコード5 場所を検索する5.1 サンプルコード6 画面例7 さ ...

react-icon

React Big Calendarの複数タイムゾーン対応

1 はじめに2 端末のタイムゾーンのみに対応する場合3 複数のタイムゾーンに対応する。3.1 日時を指定のタイムゾーンに変換する3.2 イベントの開始日時・終了日時を動的に設定する3.3 ラップクラス ...

[Next.js] netlifyからCloudflare Pagesに引っ越してみた

1 はじめに2 netlify vs Cloudflare Pages3 Cloudflare Pagesへのデプロイ4 netlifyでのリダイレクト設定とビルド停止5 さいごに6 おすすめ書籍 は ...

[Next.js]FirestoreのデータをServer Componentから取得する

1 はじめに2 Next.jsでFirestoreからデータを取得する方法2.1 Client Componentで直接Firestoreから取得2.2 Route Handlerを使ってAPI化し、 ...

react-icon

Vite 3を使ってみた

1 はじめに2 なぜViteは早いのか2.1 Native ESMの活用2.2 esbuildによる事前バンドル3 Viteのセットアップ3.1 Reactテンプレートでのセットアップ3.2 vite ...

フォロー

blog-page_side_responsive

2022年4月
 12
3456789
10111213141516
17181920212223
24252627282930

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。