はじめに
React(Next.js/GraphQL)からHasuraを使ったCRUD操作を何回かに分けて見ていきます。
今回は、CRUDのC(Create)について見ていきます。
最終的なゴール
以下のような構成のアプリを作ることです。
目的
- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上
ベースとなる記事のリンク
この記事は以下の記事がベースとなっております。
全体のコードなどはそちらに記載があります。
詳細👇
Createに関するカスタムフック
使う関数はuseMutation
です。というか、R
以外は、useMutation
と思っても良いかも。
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
ですね。
型定義はこんな感じ。
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オプションの引数で現状のキャッシュとレスポンスのオブジェクトが受け取れるので、これを利用してキャッシュを更新します。
戻り値を元に一覧のキャッシュを更新できます。
詳細は👇
クローズアップするとこんな感じ
update(cache, { data: { insert_users_one } }) {
const cacheId = cache.identify(insert_users_one)
cache.modify({
fields: {
users(existingUsers, { toReference }) {
return [toReference(cacheId), ...existingUsers]
},
},
})
}
仮にコレをA
とすると、以下のようなコードになりますね。
const [insert_users_one] = useMutation<CreateUserMutation>(CREATE_USER, A)
関数useMutation
の第二引数ということがわかります。
CREATE_USER
の中身を見ると、
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つのユーザー情報が返ってきます。
それをこちら👇で受け取っていることがわります。
次に、以下で、キャッシュのIDを取得することができます。
cache.identify()
つまり、作成したuserのキャッシュのidを取得します。
以前、どこかの記事で説明したかもしれませんが、キャッシュは__typename
とid
を組み合わせて作成します。
その組み合わせをキャッシュのkeyとして変数cacheId
に格納されます。
例 users:7c7fdd99-4e42-4fc5-b24d-b9fa49ee2345
こんな感じのデータが格納されます。
続いて、toReference
の引数に変数cacheId
を渡すと、idをkeyとして、作成したユーザー情報が展開されます。
cache.modify({
fields: {},
})
fields
部分は、更新したいfieldを指定できます。指定したら。そのフィールドが更新されます。
今回は、users
フィールドを書き換えるので、users
を指定しています。
users
の第一引数には既存のキャッシュの配列を取得できます。それをexistingUsers
という名前で受け取ります。
キャッシュの更新自体はここの処理です。
return [toReference(cacheId), ...existingUsers]
配列の中にある
-
existingUsers
をスプレッドで展開してる -
toReference(cacheId)
これで、作成したユーザー情報を展開している
これで、配列の先頭に新規作成したユーザーが足されてruturn
されているとわかります。
これが、キャッシュに新規作成ユーザーを追加するまでの過程です。
新規ユーザーを作成
試しに、新規ユーザーを作成します。
Hasuraからも追加できたことがわかります。
これから、キャッシュの検索key()はusers:7c7fdd99-4e42-4fc5-b24d-b9fa49ee2345
であるとわかりますね。
Networkみると、以下のようなJsonデータが、GraphQlに送られていたことがわかります。
{
"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の流れはこんな感じです。
今日のところは以上です。
次回以降で、他の処理も見てきます。ありがとうございました。
参考
アウトプット100本ノック実施中