React（Next.js/GraphQL）からHasuraを使ったCRUD操作 〜CRUDのC（Create）について〜

## はじめに

React（Next.js/GraphQL）からHasuraを使ったCRUD操作を何回かに分けて見ていきます。

今回は、CRUDのC（Create）について見ていきます。

## 最終的なゴール

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

![スクリーンショット 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)

### 目的

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

## ベースとなる記事のリンク

この記事は以下の記事がベースとなっております。

全体のコードなどはそちらに記載があります。

詳細👇

https://qiita.com/ryosuketter/items/d9106135dd81bee3c038

## Createに関するカスタムフック

使う関数は`useMutation`です。というか、`R`以外は、`useMutation`と思っても良いかも。

```tsx:pages/hasura-crud.tsx
const [insert_users_one] = useMutation<CreateUserMutation>(CREATE_USER, {
    update(cache, { data: { insert_users_one } }) {
      const cacheId = cache.identify(insert_users_one)
      cache.modify({
        fields: {
          users(existingUsers, { toReference }) {
            return [toReference(cacheId), ...existingUsers]
          },
        },
      })
    },
  })
```

ジェネリクスの型は`./types/generated/graphql`から来た`CreateUserMutation`ですね。

型定義はこんな感じ。

```ts
export type CreateUserMutation = {
  __typename?: 'mutation_root'
  insert_users_one?:
    | { __typename?: 'users'; id: any; name: string; created_at: any }
    | null
    | undefined
}
```

### キャッシュ更新部分

Updateの場合は、Apolloがキャッシュ内の各オブジェクトの __typename と id を見て、レスポンスの内容と一致するものを自動で更新してくれます。

ですが、CreateとDeleteの場合は、処理が終わったとに、キャッシュが自動的に更新されない仕様になっています。

なので、Createの処理が終わった後、`update`という関数を使っていきます。

updateオプションの引数で現状のキャッシュとレスポンスのオブジェクトが受け取れるので、これを利用してキャッシュを更新します。

戻り値を元に一覧のキャッシュを更新できます。

詳細は👇

https://www.apollographql.com/docs/react/data/mutations/#updating-the-cache-after-a-mutation

クローズアップするとこんな感じ

```tsx
update(cache, { data: { insert_users_one } }) {
  const cacheId = cache.identify(insert_users_one)
  cache.modify({
    fields: {
      users(existingUsers, { toReference }) {
        return [toReference(cacheId), ...existingUsers]
      },
    },
  })
}
```

仮にコレを`A`とすると、以下のようなコードになりますね。

```tsx
const [insert_users_one] = useMutation<CreateUserMutation>(CREATE_USER, A)
```

関数`useMutation`の第二引数ということがわかります。

`CREATE_USER`の中身を見ると、

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

戻り値が以下であるとわかります。

```
id
name
created_at
```

帰ってくる時のフィールド名が`insert_users_one`という名前で1つのユーザー情報が返ってきます。

それをこちら👇で受け取っていることがわります。

![Qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/72dfc7a8-20df-7379-fccc-ef3ab10f2b0a.png)

次に、以下で、キャッシュのIDを取得することができます。

```ts
cache.identify()
```

つまり、作成したuserのキャッシュのidを取得します。

以前、どこかの記事で説明したかもしれませんが、キャッシュは`__typename`と`id`を組み合わせて作成します。

その組み合わせをキャッシュのkeyとして変数`cacheId`に格納されます。

例 `users:7c7fdd99-4e42-4fc5-b24d-b9fa49ee2345`

こんな感じのデータが格納されます。

続いて、`toReference`の引数に変数`cacheId`を渡すと、idをkeyとして、作成したユーザー情報が展開されます。

```ts
cache.modify({
  fields: {},
})
```

`fields`部分は、更新したいfieldを指定できます。指定したら。そのフィールドが更新されます。

今回は、`users`フィールドを書き換えるので、`users`を指定しています。

`users`の第一引数には既存のキャッシュの配列を取得できます。それを`existingUsers`という名前で受け取ります。

キャッシュの更新自体はここの処理です。

```ts
return [toReference(cacheId), ...existingUsers]
```

配列の中にある

- `existingUsers`をスプレッドで展開してる
- `toReference(cacheId)`これで、作成したユーザー情報を展開している

これで、配列の先頭に新規作成したユーザーが足されて`ruturn`されているとわかります。

これが、キャッシュに新規作成ユーザーを追加するまでの過程です。

#### 新規ユーザーを作成

試しに、新規ユーザーを作成します。

![Hasura_CRUD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/b84bd638-7888-bd6a-c8f9-6fcfda7c7ff5.png)

Hasuraからも追加できたことがわかります。

![Browse_-_users_-_Data___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/ed1d51f0-9d63-1876-3073-4bd4246ce292.png)

これから、キャッシュの検索key（）は`users:7c7fdd99-4e42-4fc5-b24d-b9fa49ee2345`であるとわかりますね。

Networkみると、以下のようなJsonデータが、GraphQlに送られていたことがわかります。

```json

{
   "operationName":"CreateUser",
   "variables":{
      "name":"aaa"
   },
   "query":"mutation CreateUser($name: String!) {\n  insert_users_one(object: {name: $name}) {\n    id\n    name\n    created_at\n    __typename\n  }\n}\n"
}

```

CRUDのCの流れはこんな感じです。

今日のところは以上です。

次回以降で、他の処理も見てきます。ありがとうございました。

## 参考

https://tech.mof-mof.co.jp/blog/apollo-with-cache-intro/

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

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