🐬

SWRライブラリを利用したGraphQL APIデータ取得

2022/07/19に公開

はじめに

  • 以下の記事ではREST APIよりデータ取得したが、GraphQL APIよりデータを取得する。

https://zenn.dev/hiroharu8864/articles/f92e4d83cd0023

  • Suspenseコンポーネントを利用し、SWRライブラリ経由でデータ取得、その取得結果をコンポーネントへ表示。まずは基本動作。
  • GitHub GraphQL APIよりデータを取得する。
  • SWRライブラリはVercel社作成ライブラリで、詳細は他の記事が詳しい。
    Suspenseタグ内部のコンポーネントのローディングが完了していない場合、propsのfallbackの内容を表示する。

GitHub APIアクセストークン取得

  • 取得したアクセストークンを利用し、API経由で情報取得できることを確認する。
    • ghp_token 部分に取得したトークンを入力する。
    • ヘッダーには「Authorization: bearer」部分まで含めて情報が必要。"data"部のデータ取得を確認。
curl --insecure -H "Authorization: bearer ghp_token" -X POST -d " \
 { \
   \"query\": \"query { viewer { login }}\" \
 } \
" https://api.github.com/graphql
{"data":{"viewer":{"login":"hiroharu8864"}}}

SWRライブラリによるARI呼び出し ./src/components/hooks/getLoginUser.ts(カスタムフック)

  • useSWR
    • 1番目引数(key): queryと各variable を配列で指定。key値となるため、variableを合わせて渡す。
    • 2番目引数(fetcher): データをフェッチし、Promiseを返す関数を指定。
    • 3番目引数(option): オプション指定。この部分に{ suspense: true }を指定する。
    • useSWRで取得するデータの戻り値の型を指定。
  • getLoginUserQueryで指定したクエリで、データ取得できることを事前にGitHub Explorerにて確認しておく。
import { GraphQLClient } from "graphql-request";
import useSWR from "swr";
import { GitHubData } from "../types/GitHubData";

const getLoginUserQuery = `
query loginUserQuery(
  $loginUser: String!
  ) { 
  user(login: $loginUser){
    id
    login
    url
  }
}
`;
const loginUser = "hiroharu8864";

export const getLoginUser = () => {
  const access_token = "ghp_token";
  const client = new GraphQLClient("https://api.github.com/graphql", {
    headers: {
      Authorization: `bearer ${access_token}`,
      "Content-Type": "application/json"
    },
    method: "POST"
  });

  const { data, error } = useSWR<GitHubData>(
    [getLoginUserQuery, loginUser],
    (query, login) => client.request(query, { loginUser: login }),
    {
      suspense: true
    }
  );
  return { data, error };
};

APIレスポンスの型指定 ./src/types/GitHubData.ts

  • GraphQL APIの返り値をコンソールログで確認すると以下の型となっている。
    • 第一階層: User型を1つ持つObject型
    • 第二階層: id, login, urlを持つUser型
  • なので、以下のとおり型を定義

export type GitHubData = {
  user: User;
};
type User = {
  id: string;
  login: string;
  url: string;
};

出力表示するコンポーネント ./src/components/pages/GraphQLFetch.tsx

import { FC, memo, Suspense, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { getLoginUser } from "../../hooks/getLoginUser";

const ResultComponent = () => {
  const { data, error } = getLoginUser();
  return (
    <>
      <h2>Fetch Login Users Data is below</h2>
      <div>
        <p>{data?.user.id}</p>
        <p>{data?.user.login}</p>
        <p>{data?.user.url}</p>
      </div>
    </>
  );
};

export const GraphQLFetch: FC = memo(() => {
  const navigate = useNavigate();
  const onClickHome = useCallback(() => {
    navigate("/");
  }, [navigate]);
  return (
    <>
      <Suspense fallback={<p>厄介な広告ページの表示</p>}>
        <ResultComponent />
      </Suspense>
      <button onClick={onClickHome}>to HOME</button>
    </>
  );
});
  • 取得できましたー。

Repository

https://github.com/hiroharu8864/react-swr-graphql-fetch

  • Reactの流儀に従うことで、ページのレンダリングとAPIリクエストのタイミングを意識することなく、コーディングできる。

Discussion