はじめに
React(Next.js/GraphQL)からHasuraを使ったCRUD操作を何回かに分けて見ていきます。
今回は、CRUDのD(Delete)について見ていきます。
最終的なゴール
以下のような構成のアプリを作ることです。
目的
- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上
ベースとなる記事のリンク
この記事は以下の記事がベースとなっております。
全体のコードなどはそちらに記載があります。
詳細👇
Deleteに関するカスタムフック
使う関数はuseMutation
です。というか、R
以外は、useMutation
と思っても良いかも。
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
の中身を見ると、
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つのユーザー情報が返ってきます。
それをこちら👇で受け取っていることがわります。
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
されているとわかります。
ユーザーの削除
試しに、ユーザーを削除します。
Hasuraからも削除できたことがわかります。
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本ノック実施中