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アプリケーション開発

page_footer_responsive




-FrontEnd
-, ,

執筆者:

免責事項

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


comment

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

CAPTCHA


関連記事

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

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

[Rails + Materialize] パンくずリスト用のヘルパーを作成した

1 はじめに2 パンくずリストを上書き2.1 サンプルのHTML2.2 CSSの上書き3 ヘルパーにする4 さいごに はじめに またまたMaterialize関連の記事になります。 Materiali ...

Vue.js入門その6〜RouterとComponentを使ってTODOアプリを修正〜

1 はじめに2 vue-routerのインストール3 サーバーサイドの改修3.1 APIに詳細(show)を追加3.2 元となるビューファイルを作成3.3 ルーティングの修正4 Vue.jsの実装4. ...

react-icon

[React初心者]カスタムフックについて学ぶ

1 はじめに2 Ract Hook(フック)とは3 カスタムフックの実装3.1 フックのルール3.2 カスタムフック3.3 カスタムフックの実装4 さいごに5 おすすめ書籍 はじめに 今回はReact ...

JQueryでformにinput要素を足していく

はじめに 最近個人的にディープラーニングの勉強をしているtonnyです。 ディープラーニングの勉強がてら、好きな麻雀に関するWebアプリを作成してみました。 今回はその作成の中で、今まであまりやってこ ...

フォロー

blog-page_side_responsive

2022年4月
 12
3456789
10111213141516
17181920212223
24252627282930

アプリ情報

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