何をするか?
GitHub の GraphQL API で Issue 情報などを取得しようとすると、リソース制限 のため一度に 100 件までの情報しか取得できません。
Apollo Client が提供する useQuery
や useLazyQuery
などの React フック関数を使用すると、戻り値で返される fetchMore
関数を使って追加読み込み(ページネーション処理)を行うことができますが、この関数の使用例として提示されているものは、ユーザーによるボタンクリックなどを必要とするものばかりです。
ここでは、useQuery
実行後に自動で fetchMore
を繰り返し呼び出して、100 件を超える情報を取得する方法の例を示します。
fetchMore のための設定
前提として、Apollo Client の fetchMore
関数の基本的な使い方は理解しているものとします(下記記事などを参考にしてください)。
今回サンプルコードで使う GraphQL クエリには、次のような search
コネクションが含まれていることを想定しています。
ページネーションの対象となるのは、この search
コネクション部分です。
そのため、ApolloClient
に設定するキャッシュのフィールドポリシーとして、search
フィールドの値が fetchMore
時にマージされるように設定しておきます。
cache
オブジェクトの生成時に呼び出している relayStylePagination
関数あたりがポイントです。
あとは、上記ファイルで export されている GitHubApolloProvider
コンポーネントをトップレベルのコンポーネントとして配置すれば、それ以下の階層で useQuery
フックが適切に動作するようになります。
例えば、Next.js を使っている場合なら、カスタム App コンポーネントで次のような感じで配置すればよいでしょう。
fetchMore を自動呼出しするためのフック関数 (useAutoFetchMore) を作る
fetchMore
を自動で繰り返し呼び出す仕組みですが、ここでは useEffect
を使って、pageInfo.hasNextPage
の値などが変化したときに fetchMore
を呼び出すようにしてみます。
この実装をコンポーネントのコードに入れてもいいのですが、ある程度汎用的に使える処理なので、useAutoFetchMore
フック関数として定義します。
useAutoFetchMore フックの使用例
次のサンプルコンポーネントは、上記で作成した useAutoFetchMore
フックを使用して、GitHub の apollographql/apollo-client
リポジトリの Issue 情報を連続取得します。
一度に取得する件数は first: 100
のように最大 100 件に設定することができますが、ここでは連続して取得していることが分かるように first: 5
として 5 件ずつ取得するようにしています。
ポイントは、下記のフック呼び出し部分です。
useQuery
フックに続けて useAutoFetchMore
フックを呼び出しておくことで、内部で fetchMore
が自動的に繰り返し呼ばれるようになります。
内部で fetchMore
が呼び出されるごとにコンポーネントの再描画が行われるため、段階的に表示量が増えていく振る舞いになります。
応用(useLazyQuery)
Apollo Client において、任意のタイミング(ボタンクリックなど)で GraphQL クエリを発行したいときは、useQuery
の代わりに useLazyQuery
フックを使用します。
今回実装した useAutoFetchMore
フックは、そのまま useLazyQuery
にも適用することができます(クエリが実行されるまでは、内部的に hasNextPage == false
と同じ振る舞いになるようにしているので)。
次のサンプルコードでは、ユーザーが Get Issues
ボタンをクリックしたときに fetchMore
の自動実行を開始するようにしています。
関連記事