5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-11-07

はじめに

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

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

最終的なゴール

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

スクリーンショット 2021-10-18 17.27.41.png

目的

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

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

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

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

詳細👇

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

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

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ですね。

型定義はこんな感じ。

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

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

詳細は👇

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

    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とすると、以下のようなコードになりますね。

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

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

DELETE_USERの中身を見ると、

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

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はキャッシュから消す。処理がコレです。

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

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

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

ユーザーの削除

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

340d90e31f100b964265d2351a24ef99.gif

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

スクリーンショット 2021-11-08 1.00.29.png

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


{
   "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の流れはこんな感じです。

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

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

参考

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

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?