You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何删除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查询的缓存都会被清除,下次组件渲染时会自动重新发起请求获取最新数据,完美覆盖所有复杂的filterorderBy组合。

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

火山引擎 最新活动