React（Next.js/GraphQL）とHasuraの連携するまでの過程メモ

## はじめに

この記事はチュートリアルではなく、最終的なゴールがあってその途中過程のメモです。

読みづらいところもあるかもしれませんが、ご了承ください。

## 最終的なゴール

以下のような構成のアプリを作ることです。

![スクリーンショット 2021-10-18 17.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e8a9a2e1-2723-4fec-77ef-be3b9eefdd81.png)

### 目的

- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上

## 過程

以下の開発環境の構築は行ったものとします

- Next.js導入
- Hasura導入

Hasuraに関しては、以下の記事をはじめ何記事かにわたって、導入までの紹介しております。

https://qiita.com/ryosuketter/items/8b01d53d0609f78c2e0e

### apollo導入

Next.js導入終わったら、apolloに関するパッケージをインストールしました。

```
yarn add @apollo/client graphql @apollo/react-hooks cross-fetch @heroicons/react
```

heroiconsとかは若干関係ないのですが使用するので一緒に `yarn add` しています。

https://softantenna.com/wp/review/heroicons/

### GraphQL

データ型を自動生成する`codegen`を導入

```
yarn add -D @graphql-codegen/cli
```

続いて初期化

```
yarn graphql-codegen init
```

すると、設定値をインタラクティブに決めていきます。

自分が設定した過程は以下

```
yarn graphql-codegen init

yarn run v1.22.17
warning ../../package.json: No license field
$ /Users/ryosuke/Project/nextjs-hasura-basic-lesson/node_modules/.bin/graphql-codegen init

    Welcome to GraphQL Code Generator!
    Answer few questions and we will setup everything for you.

? What type of application are you building? Application built with React
? Where is your schema?: (path or url) https://ryosuketter-hasura-test.hasura.app/v1/graphql
? Where are your operations and fragments?: queries/**/*.ts
? Pick plugins: TypeScript (required by other typescript plugins), TypeScript Operations (operations a
nd fragments), TypeScript React Apollo (typed components and HOCs)
? Where to write the output: types/generated/graphql.tsx
? Do you want to generate an introspection file? No
? How to name the config file? codegen.yml
? What script in package.json should run the codegen? gen-types
Fetching latest versions of selected plugins...

    Config file generated at codegen.yml

      $ npm install

    To install the plugins.

      $ npm run gen-types

    To run GraphQL Code Generator.

✨  Done in 297.49s.
```

Hasuraの導入をあらかじめ行ったので、schemaの場所を尋ねられても、GraphQL の Endpointを設定することができます。

下記は既にHerokuを使って本番環境にデプロイされております。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e06c7f42-9b0e-ea8c-2f6d-afd3fcd0b6b9.png)

```
Where are your operations and fragments?
```

こちらに関して

まず、codegenというのは、Projectの中に定義されているクエリの内容を読んで自動的に解析を行います。

この質問は、クエリの内容がどの場所にあるかを聞かれています。

その場所が

```
queries/**/*.ts
```

ということです。サブフォルダも含めてここにありますよ。という意味です。

```
? Where to write the output: types/generated/graphql.tsx
```

型を自動生成したファイルの出力先とその回答です。

```
? What script in package.json should run the codegen? gen-types
```

`codegen`実行スクリプト名の定義ですね。`gen-types`にしたので

```
yarn gen-types
```

とすれば、型の自動生成が始まります。

あとは、

```
yarn
```

すれば、これまでの設定した内容がインストールされます。

codegenのTSモジュールもインストール

```
yarn add -D @graphql-codegen/typescript
```

場所`/queries/queries.ts`に、以下の内容のクエリを作成します。

基本的にはHasuraの管理画面でほぼ自動作成してくれました。

- GET_USERS: ユーザー一覧を取得するクエリ（サーバーサイドから）
- GET_USERS_LOCAL：　ユーザー一覧を取得するクエリ（クライアント、つまりキャッシュから）
- GET_USERSIDS: ユーザーidをGETするクエリ
- GET_USERBY_ID: idから1ユーザーをGETするクエリ
- CREATE_USER: ユーザー作成のクエリ
- DELETE_USER: ユーザー削除のクエリ
- UPDATE_USER: ユーザー情報更新のクエリ

```ts:/queries/queries.ts

import { gql } from '@apollo/client'

export const GET_USERS = gql`
  query GetUsers {
    users(order_by: { created_at: desc }) {
      id
      name
    }
  }
`

export const GET_USERS_LOCAL = gql`
  query GetUsers {
    users(order_by: { created_at: desc }) @client {
      id
      name
    }
  }
`

export const GET_USERSIDS = gql`
  query GetUserIds {
    users(order_by: { created_at: desc }) {
      id
    }
  }
`

export const GET_USERBY_ID = gql`
  query GetUsersById($id: uuid!) {
    users_by_pk(id: $id) {
      id
      name
      created_at
    }
  }
`

export const CREATE_USER = gql`
  mutation CreateUser($name: String!) {
    insert_users_one(object: { name: $name }) {
      id
      name
      created_at
    }
  }
`

export const DELETE_USER = gql`
  mutation DeleteUser($id: uuid!) {
    delete_users_by_pk(id: $id) {
      id
      name
      created_at
    }
  }
`

export const UPDATE_USER = gql`
  mutation UpdateUser($id: uuid!, $name: String!) {
    update_users_by_pk(pk_columns: { id: $id }, _set: { name: $name }) {
      id
      name
      created_at
    }
  }
`

```

クエリに対して、TSに必要な型の自動生成を、先ほど用意した

```
yarn gen-types
```

を実行します。

クエリ名が被ってるので、`GET_USERS_LOCAL`だけコメントアウトしました。

自動生成は完了すると、自分が設定した箇所に、以下のファイルが生成されました。

`types/generated/graphql.tsx`

これで、クエリの型の自動生成が完了しました！:smiley:

本日は以上です。

## 参考

https://hasura.io/learn/ja/graphql/hasura/relationships/

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103