ReactでGraphQL - Apollo Client編

# ReactでGraph QLを使いたい

担当サービスでGraph QLを導入する可能性があるため、React側でこれを使用するために必要なことを調べようと思いました。

とりあえず、候補として、

- Apollo Client
- Relay

の二つが上がったんですが、前者の方がドキュメントが親切なようなので、こちらをまずターゲットとします。

ただし、Relayの方も調査をしておきたいです。Reactのv18以降、suspenseでの非同期処理が本格的に導入される際、Realyがまず対応してくることと思います。（というか現時点で既にある程度対応しているっぽい？）今後の調査対象とします。


## Apollo Client導入
apollo-boostは廃止されたようなので、`@apollo/client`を使用します。
[ApolloClient公式](https://www.apollographql.com/docs/react/get-started/)を参考に進めていきます。

apollo clientを公式の通り導入します。  
`create-react-app example-apollo`
`yarn add @apollo/client graphql`

clientを作成します。
今回は、githubのGraphQL APIを使用するのでclientはgithubへのURLを使用します。
token情報が必要なので、clientにauthorizationヘッダを追加し、tokenを記載する必要があります。
githubのtokenは予め取得し、.envファイルに記載してあるので環境変数として取得できます。(githubのtokenについては後述)

```Javascript
// index.js

const httpLink = createHttpLink({
  uri: "https://api.github.com/graphql",
});

const authLink = setContext((_, { headers }) => {
  const token = process.env.REACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN;
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
    },
  };
});

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
});
```

clientを作成したら、`ApolloProvider`に作成したclientを渡し、ApolloProviderを親コンポーネントとします。
子のコンポーネントとして、MainContentを使っていますが、後で作ります。

```Javascript
<ApolloProvider client={client}>
  <MainContent />
</ApolloProvider>
```

次はqueryを作成します。
検索対象を

- githubのリポジトリで
- READMEに`react`や`vue`や`angular`という語が含まれているもの

を検索するようにします。
githubのドキュメントを見ながら、Explorerで以下のように試したクエリを投げてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408437/c5f041d6-303b-aa2b-f953-c008feaff7c2.png)

```Javascript
// index.js

import { gql } from "@apollo/client";

export const repositoryQuery = gql`
  {
    search(type: REPOSITORY, query: "react in:readme", last: 20) {
      repositoryCount
      nodes {
        ... on Repository {
          id
          url
          name
          description
          createdAt
        }
      }
    }
  }
`;
```

これでがクエリの用意ができました。

あとは、useQueryフックに、作成したクエリを渡してやればクエリを投げてくれます。

```Javascript
// mainContent.js

import { useQuery } from "@apollo/client";
import { repositoryQuery } from "./graphQl/query";

const MainContent = () => {
  const { loading, data } = useQuery(repositoryQuery);

  if (loading) return "...";
  return (
    <ul>
      {data.search.nodes.map((r, i) => (
        <li key={i}>
          <a href={r.url}>{r.url}</a>
        </li>
      ))}
    </ul>
  );
};

export default MainContent;
```

こんな感じで`yarn start`すると、githubのrepositoryを検索した結果が取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408437/7dd4453c-6ce9-3c27-fd65-40ccf4f1b7ad.png)

簡単な構成ですが、これでGraphQLのクエリを使用することができました。

これを少し発展させ、`react` `vue` `angular`それぞれの語で検索できるようにしたものが↓にあります。
https://github.com/masaka-ghub/react-apollo/tree/exam_apollo



## githubのトークン

githubのAPIは使用するためにトークンが必要です。
発行方法は
アカウントアイコン→settings→Developer settings→personal access tokensと進むと、下のような画面が出るので`Generate new token`を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408437/2ed8ead6-c140-831d-c86f-8a217c88e4d3.png)


あとは名前と、必要なものにチェックをつけて作成してください。(今回はrepo以下とuser以下の項目にチェックをつけましたが、用途に合わせてチェックしてください。)

プロジェクトのルートに`.env`ファイルを作成し、
```
REACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN=<githubにtokenとして表示された文字列>
```
と記載すると`process.env.REACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN`としてコード内で使用できるようになります。