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

## はじめに

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

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

## 最終的なゴール

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

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

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

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

```tsx:pages/hasura-crud.tsx
const [delete_users_by_pk] = useMutation<DeleteUserMutation>(DELETE_USER, {
    update(cache, { data: { delete_users_by_pk } }) {
      cache.modify({
        fields: {
          users(existingUsers, { readField }) {
            return existingUsers.filter(
              (user) => delete_users_by_pk.id !== readField('id', user)
            )
          },
        },
      })
    },
  })
```

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

型定義はこんな感じ。

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

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

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

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

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

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

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

詳細は👇

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

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

```tsx
    update(cache, { data: { delete_users_by_pk } }) {
      cache.modify({
        fields: {
          users(existingUsers, { readField }) {
            return existingUsers.filter(
              (user) => delete_users_by_pk.id !== readField('id', user)
            )
          },
        },
      })
    },
```

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

```tsx
const [delete_users_by_pk] = useMutation<DeleteUserMutation>(DELETE_USER, A)
```

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

`DELETE_USER`の中身を見ると、

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

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

```
id
name
created_at
```

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

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

![hasura-crud_tsx_—_nextjs-hasura-basic-lesson.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/0e3e9c7f-05fb-d12d-46cc-1c81bfcb040c.png)

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

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

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

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

`users`の第2引数`readField`はapolloの機能で使えるやつで、任意のFieldの値を読むことができます。

今回であれば、`existingUsers`を配列処理系関数のfilterで、ユーザーを1つ1つ展開しています。

`readField('id', user)`では、idのFieldを読んで

削除した`delete_users_by_pk.id`（ユーザーのid）に一致しないuserのid達を残す。

つまり、一致したidはキャッシュから消す。処理がコレです。

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

```ts
return existingUsers.filter(
  (user) => delete_users_by_pk.id !== readField('id', user)
)
```

これが、`ruturn`されているとわかります。

#### ユーザーの削除

試しに、ユーザーを削除します。

![340d90e31f100b964265d2351a24ef99.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/d963bfd1-667e-6436-c2aa-86f8205385a2.gif)

Hasuraからも削除できたことがわかります。

![スクリーンショット 2021-11-08 1.00.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/118926db-8f26-bb62-7ae4-6f94b24eabb6.png)

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

```json

{
   "operationName":"DeleteUser",
   "variables":{
      "id":"7c7fdd99-4e42-4fc5-b24d-b9fa49ee2345"
   },
   "query":"mutation DeleteUser($id: uuid!) {\n  delete_users_by_pk(id: $id) {\n    id\n    name\n    created_at\n    __typename\n  }\n}\n"
}

```

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

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

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

## 参考

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

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

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