【Next.js】ApolloClientを使ってGraphQL APIデータを取得しよう！

GraphQLサーバーからのデータフェッチ方法はSSGやサーバー側が用意したSDKなど多様にありますが、 最近使ったApollo Clientが使いやすかったので紹介します。
なお、実装例はNext.jsを使用してGitHub GraphQL APIからデータフェッチを行います。

## Apollo Clientがおすすめな理由
[公式サイト](https://www.apollographql.com/docs/react/why-apollo "公式サイト")に色々理由が書いてありますが、この中で一番の理由はuseQueryフックがデフォルトで用意されていることかと思います。
これによって、自分でデータフェッチ用のコードを書く必要性がなくなり、従来より短いコードで実装ができるようになります。
なお、useQueryは多機能らしいのですが、自分はまだそこまで使いこなしていないのでご了承ください。

## 環境
- Next.js
- GitHub GraphQL APIでデータを取得するための準備が出来ている
（GitHubトークンを取得し、エクスプローラーなどでクエリーが作成できている）
※GraphQL APIの使い方は割愛します。

## 実装その１ パッケージのインストール
１から５までは[公式サイト](https://www.apollographql.com/docs/react/get-started "公式サイト")のステップ２～５をそのまま引用したものです。実装の基本は公式ドキュメントなので、まずは公式ドキュメントを見ながら手を動かしてみて、つまったら参考サイトを活用することをお勧めします。私も心掛けています。現実は厳しいですが・・・涙
インストールに関してはステップ２のとおり
```javascript
npm install @apollo/client graphql
```
または
```javascript
yarn add @apollo/client graphql
```
をインストールしてください。

## 実装その２　ApolloClientインスタンスの初期化（クライアント情報の作成）
ApolloClientのインスタンスを新たに生成します。
uriはエンドポイントを指定します。[GitHub GraphQL APIのエンドポイントはこちら](https://docs.github.com/ja/graphql/guides/forming-calls-with-graphql "GitHub GraphQL APIのエンドポイントはこちら")

:::note alert
公式の例にはありませんが、インスタンス作成の際にユーザーを認証する情報が必要になります。
GitHub GraphQL APIの場合だとheadersにアクセストークン情報が必要なので、それを追記しています。
なお、アクセストークン情報の直書きは厳禁です。環境変数を使いましょう。
:::

ファイルはライブラリ関係だとlibが使われることが多いので、以下のパスに作成しました。
/src/lib/apollo/apolloClient.ts
```javascript
export const apolloClient = new ApolloClient({
  cache: new InMemoryCache(),
  headers: { authorization: `Bearer ${process.env.GH_TOKEN}` },
  uri: "https://api.github.com/graphql",
});
```

## 実装その３　クライアント情報をセットする。
その２で作成したクライアント情報をインポートしてReact側に渡します。
まずは_app.tsx(jsx)内に作成したクライアント情報（その２で作成したapolloClient）とApolloProviderをインポートします。
ApolloProviderはコンポーネントとして、\<Component {...pageProps} />をラップする形で設置してください。
あとは、インポートしたクライアント情報を引数としてApolloProviderコンポーネントに渡せばＯＫです。
以下が_app.tsx(jsx)の例です。
```javascript
import "../styles/globals.css";
import type { AppProps } from "next/app";
import { ApolloProvider } from "@apollo/client";
import { apolloClient } from "src/lib/apollo/apolloClient";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ApolloProvider client={apolloClient}>
      <Component {...pageProps} />
    </ApolloProvider>
  );
}

export default MyApp;

```

この作業により、**どのページからもデータをフェッチすることができる**ようになりました。すごいですね！

## 実装その４　useQueryを使ってデータフェッチを行う
その３でどのページからもデータをフェッチすることができるとお伝えしましたが、方法はuseQueryを使用します。
まずはNext.jsのpages配下に任意のページ用ファイルを作成してください、

次に、そのページ内にエンドポイントからデータフェッチする際のクエリ情報を定義します。
内容は、5件分のリポジトリを最新の更新順に取得するもので、作成日や更新日、リポジトリのURL情報などがとれるように設定しています。
```javascript
const GET_REPOSITORIES = gql`
  query UseGitHubInfo {
    user(login: "topaoad") {
      name
      url
      repositories(last: 5, orderBy: { field: UPDATED_AT, direction: ASC }) {
        totalCount
        nodes {
          name
          description
          createdAt
          updatedAt
          url
          forkCount
          stargazerCount
          languages(orderBy: { field: SIZE, direction: DESC }, last: 10) {
            totalCount
            totalSize
            edges {
              node {
                id
                name
                color
              }
              size
            }
          }
        }
      }
    }
  }
`;

```
もしクエリの作成がまだでしたら、以下のページで作成してください。

https://docs.github.com/ja/graphql/overview/explorer


次に、先ほど定義したクエリ情報を使ってuseQueryでフェッチします。
ページのメインコンポーネント内のreturn文の前に以下のように書いてください。
すると、先ほどのクエリ情報を元にGitHub GraphQL APIからデータを取得し、data内に格納されます。
あとは、dataで取得したデータを使って、map関数などを用いて好き好きに実装をしてください！！
```javascript
const Apollotest: NextPage = () => {
  const { data, error, loading } = useQuery<UseGitHubInfoQuery>(
    GET_REPOSITORIES
  );

  return 
};

export default Apollotest;
```

## 実装その５　取得したデータに型定義を行う。
公式サイトの案内はここまでですが、実はもう一つやりたいことがあります。
それは、「取得したデータの自動型付け」です。
その４のuseQueryに\<UseGitHubInfoQuery>というジェネリック型の型定義あるのにお気づきですか？
これは、GraphQL Code Generatorを用いて型定義ファイルを作成した際のものを引用しているのです。

詳しい作成方法は[こちらの記事](https://qiita.com/toproad/items/f2621c5b44c62ad9f21c "こちらの記事")で紹介してますので、よければご覧ください。
引用したファイルについて簡単に説明しますと、型定義ファイル作成の際に標準で設定されているプラグイン
「Tpescript-operations」により、クエリと対になる型定義が自動で作成されます。
これを活用しているのです。
なお、typeの型定義名は「自分がつけたクエリ名+Query」となります。
私が命名したクエリ名がUseGitHubInfoだったので、下記例はUseGitHubInfoQueryとなります。

```javascript
export type UseGitHubInfoQuery = {
  __typename?: "Query";
  user?: {
    __typename?: "User";
    name?: string | null;
    url: any;
    repositories: {
      __typename?: "RepositoryConnection";
      totalCount: number;
      nodes?: Array<{
        __typename?: "Repository";
        name: string;
        description?: string | null;
        createdAt: any;
        updatedAt: any;
        url: any;
        forkCount: number;
        stargazerCount: number;
        languages?: {
          __typename?: "LanguageConnection";
          totalCount: number;
          totalSize: number;
          edges?: Array<{
            __typename?: "LanguageEdge";
            size: number;
            node: {
              __typename?: "Language";
              id: string;
              name: string;
              color?: string | null;
            };
          } | null> | null;
        } | null;
      } | null> | null;
    };
  } | null;
};

```

ちゃんと型があたっているか、試しにdataの上にマウスをホバーして確認します。
すると、ちゃんとあたっていることが確認できます！
![スクリーンショット (104).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2574198/95b59a06-de84-6f97-a6c9-1da599101804.png)


## まとめ
公式サイトに沿った基本的な説明でしたが、最後にプラスアルファで自動型付けの説明もさせていただきました。
自分もまだまだ応用が効かずにハマることが多々ありますが、精一杯概念の理解に努めることがスキルアップには必要不可欠だと思います。
もしご意見がありましたら、遠慮なくお申し付けください。
TwitterのDMなども大歓迎です！