mmag

ハマったことメモなど

Apolloのcache updateがやや辛そうに見える

使っているのはvue-apolloだけど。

Mutationした結果をつかってquery cacheを更新する、ということができる。これによってもう一回queryしなくてよくなるなどの効果がある。Optimistic responseと組み合わせると、迅速なフィードバックを利用者に返すことができて体験が良くなる効果も見込める。よくあるコード例は

import createCommentMutation from 'create-comment.gql'
import commentsQuery from 'comments.gql'

const newComment = { ... }

this.$apollo.mutate({
  mutation: createCommentMutation,
  variables: {
    body: newComment.body,
  },
  update: (store, { data: { createComment } }) => {
    const data = store.readQuery({ query: commentsQuery })
  
    data.comments.push(newComment)

    store.writeQuery({ query: commentsQuery, data })
  },
})

なんてやつ。store.readQueryに更新したいキャッシュのクエリを与えてキャッシュの中身を取り出し、mutationの結果を使って編集して、最後にwriteQueryでキャッシュを更新。どこか画面などに反映される。

ただ現実のアプリケーションはこんなに単純なものでもないと思っていて、例えば更新したいクエリというものがvariablesを使っていたとすると、

import createCommentMutation from 'create-comment.gql'
import commentsQuery from 'comments.gql'

const newComment = { ... }
const date = '...'

this.$apollo.mutate({
  mutation: createCommentMutation,
  variables: {
    body: newComment.body,
  },
  update: (store, { data: { createComment } }) => {
    const data = store.readQuery({
      query: commentsQuery,
      variables: { date },  // <- これ
    })
  
    data.comments.push(newComment)

    store.writeQuery({ query: commentsQuery, data })
  },
})

クエリキャッシュを取得するときもvariablesが必要になる。ということは、mutationする関数などに、mutationに必要なパラメータに加えて、どのクエリキャッシュを更新すべきか特定できるだけのパラメータを渡さないといけない。もしかすると大抵の場合はmutationに必要なパラメータから導出できるのかもしれないけど、そうでないならなんかあっちこっちからデータ引き回しそう。Vuexとかでカバーできるのか、設計が良ければそうはならないのか、はて。