如何删除Apollo Client中getAllItems查询的所有变量对应缓存?
解决Apollo Client中批量清除带复杂变量查询的缓存问题
我太懂这种烦恼了——当getAllItems查询的filter是复杂对象,还有各种orderBy组合时,创建新项目后要覆盖所有可能的缓存变量组合,常规的refetchQueries或者update方法根本顾不过来,毕竟你没法提前枚举所有可能的变量值。
下面给你几个实用的解决方案,按推荐程度排序:
1. 批量清除所有getAllItems查询的缓存(最推荐)
Apollo Client的缓存条目是用「查询名称+变量哈希」作为键存储的,我们可以遍历缓存,把所有以Query:getAllItems(开头的条目都清除掉,然后触发垃圾回收彻底清理。
你可以在创建新项目的mutation的update函数里这么写:
const createItemMutation = gql` mutation CreateItem($input: ItemInput!) { createItem(input: $input) { id name # 其他需要返回的字段 } } `; // 调用mutation时的配置 useMutation(createItemMutation, { update(cache) { // 遍历缓存中的所有条目,筛选出getAllItems相关的查询缓存 cache.data.forEach((_, key) => { if (key.startsWith('Query:getAllItems(')) { cache.evict({ id: key }); } }); // 触发垃圾回收,移除无效的缓存条目 cache.gc(); }, });
这样操作后,所有getAllItems查询的缓存都会被清除,下次组件渲染时会自动重新发起请求获取最新数据,完美覆盖所有复杂的filter和orderBy组合。
2. 尝试用cache.modify批量更新列表(适合简单filter场景)
如果你的新项目符合大部分filter的条件,也可以考虑用cache.modify把新项目添加到所有匹配的getAllItems列表中。但这种方法的问题在于,你需要判断每个缓存的filter是否包含这个新项目,当filter逻辑复杂时,这个判断会非常繁琐,所以只推荐给filter规则简单的场景。
示例代码大概是这样:
update(cache, { data: { createItem } }) { cache.modify({ fields: { getAllItems(existingItems = [], { args }) { // 这里需要编写逻辑判断args.filter是否匹配createItem的属性 if (matchesFilter(createItem, args.filter)) { return [...existingItems, createItem]; } return existingItems; }, }, }); }
但还是那句话,复杂filter下这个matchesFilter函数会很难写,所以第一种方法更适合你。
3. 禁用查询缓存(应急备选)
如果你的项目列表更新特别频繁,或者你不想折腾缓存逻辑,也可以在getAllItems查询时设置fetchPolicy: 'network-only',这样每次都会直接从服务器拉取最新数据,完全绕过缓存。不过这会损失缓存带来的性能优化,所以只作为应急方案。
示例:
useQuery(GET_ALL_ITEMS, { variables: { filter, orderBy }, fetchPolicy: 'network-only', });
内容的提问来源于stack exchange,提问作者J-B




