メインコンテンツまでスキップ

GraphQL - Appolo

Mutation 時のキャッシュの更新方法

refetchQueries を使う方法

  • Mutation が成功した後に別のクエリを投げてキャッシュを更新する
  • メリット --- 簡単かつシンプル
  • デメリット --- リクエスト量が増える
createAccount({
variables: { account: data },
refetchQueries: ['GetAccounts'], // クエリ名を記載する
});

custom merge function

アイテムを削除したのちに refetchQueries で全件取得をすると、下記のようなメッセージが出る場合がある。

Cache data may be lost when replacing the accounts field of a Query object.

この場合は、下記のように custom merge function を明示的に設定してやるとよい。

const client = new ApolloClient({
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
accounts: {
// custom merge function
// - accountsを取得したときはキャッシュのデータをまるごと置き換える
// - ページネーションなどを行うときはより細かい制御が必要となる
merge: (_existingAccount, incomingAccounts) => incomingAccounts,
},
},
},
},
}),
});

update を使う方法

  • cache.modify()などを使用し、キャッシュを完全にコントロールできる
  • メリット --- リクエスト量は最少ですむ
  • デメリット --- 処理の記述が煩雑
// 作成の例
createAccount({
variables: { account: data },
update: (cache, fetchResult) => {
const newAccountRef = cache.writeFragment({
data: fetchResult.data?.createAccount?.account,
fragment: gql`
fragment NewAccountType on AccountType {
id
name
}
`,
});
cache.modify({
fields: {
accounts: (existingAccounts) => [...existingAccounts, newAccountRef],
},
});
},
});

// 削除の例
deleteAccount({
variables: { id },
update: (cache, fetchResult) => {
cache.modify({
fields: {
accounts: (existingAccounts: AccountType[], { readField }) =>
existingAccounts.filter(
(existingAccount) =>
readField('id', existingAccount) !==
fetchResult.data?.deleteAccount?.id,
),
},
});
},
});