Apollo Client で GraphQL クエリを実行するときは、カスタムフックとして useQuery
関数の呼び出し部分を抽出すると、コンポーネント側のコードをシンプルにすることができます。
分離前のコード
次のサンプルコードでは、GraphQL クエリで GitHub のログインユーザー情報を取得して表示する Viewer
コンポーネントを実装しています。
GraphQL のクエリ呼び出し部分や、取得したデータを ViewerData
オブジェクトに詰める部分などが混在しており、あまり整理されているとは言えません。
こんなときは、カスタムフックを作成して、GraphQL クエリを実行する部分や、その結果を加工する部分などを分離するとコンポーネント側のコードがシンプルになります。
分離後のコード
下記の useViewer
カスタムフックは、Apollo Client API の useQuery
呼び出し部分や、その戻り値のデータパース処理を実装しています。
useXxx
系のフック関数を呼び出すものをカスタムフックと呼びます。
カスタムフックは通常のフック関数と同様の制約を引き継ぐため、関数コンポーネント内では一定の順序で呼び出さないといけません。ポイントは、useQuery
の型パラメータとして Data
型を指定しているところです。
これにより、useQuery
の戻り値の data
プロパティの型が Data
型になります。
QueryResult
インタフェースは、Apollo Client が定義している useQuery
の戻り値の型です。
QueryResult
オブジェクトの data
プロパティは、デフォルトでは any
型ですが、QueryResult<ViewerData>
のように型パラメータを指定すると、data
プロパティを ViewerData
型として参照できるようになります。この Data
型は、下記の GraphQL クエリに対応するプロパティを保持するよう定義する必要があります(この場合、Data
型は viewer
プロパティを持つよう定義します)。
実際に useViewer
カスタムフックを使う側が参照したいのは、この Data
型のデータではなく、そこに含まれている viewer
(ViewerData
オブジェクト)の方なので、res.data.viewer
オブジェクトをリターンするようにしています。
下記は、このカスタムフックの使用例です。
とてもシンプルですね!
Viewer
コンポーネントから GraphQL クエリの呼び出し部分などが取り除かれ、UI 表現に集中して実装できるようになりました。
useViewer
フックは、データ取得前は undefined
を返し、データ取得後に ViewerData
オブジェクトを返すようにしているので、戻り値が undefined
の場合は Loading 表示などを行えば OK です。
エラー情報やローディング状態を独立した変数で返して欲しいのであれば、カスタムフックの戻り値を次のように一段ラップすればよいです。
(ただ、基本的にローディング中かどうかは viewer == undefined
で判定できるので loading
は必要ないはず)
あわせて読みたい記事
関連記事
- Apollo Client でクリック時に GraphQL クエリを実行する
- Apollo Client の Pagenation 機能を使って GraphQL API を呼び出す
- Apollo Client で GitHub GraphQL API を使う (Node & React)
- GitHub GraphQL クエリ例: マイルストーン情報を取得する (milestone)
- GitHub GraphQL クエリ例: PullRequest の情報を取得する (search)
- GitHub GraphQL クエリ例: イシュー情報を取得する (search)
- GitHub GraphQL クエリ例: リポジトリの情報を取得する (repository)