Apollo缓存错误:删除子记录后出现缓存数据丢失提示
Apollo Client缓存:处理Client.clientServices空数组合并问题
说明:此处的Client指客户个人,而非客户端/服务端。
问题场景
首次查询Client数据时,clientServices字段包含有效记录;删除一条子记录后重新查询,clientServices返回空数组,但Apollo InMemoryCache提示如下合并冲突:
existing: [{"__ref":"ClientService:46"}]
incoming: []
官方提示需为Client.clientServices定义自定义合并函数(非Apollo Client Bug),以确保缓存安全合并。
是否必须使用自定义合并函数?
不是必须,但这是最规范、可维护性最高的方案。Apollo默认的数组合并逻辑是将incoming数组元素追加到existing数组后,不会主动替换或清空。当incoming为空数组时,默认逻辑会保留原有缓存数据,与业务实际(删除后为空)冲突,因此需要自定义合并函数覆盖默认行为。
其他替代解决方案
1. 强制查询走网络而非缓存
在删除后的Client查询中,指定fetchPolicy为network-only或no-cache,直接从服务端获取最新数据,绕过缓存合并逻辑:
const { data } = useQuery(GET_CLIENT_QUERY, { variables: { clientId: targetClientId }, fetchPolicy: "network-only" });
缺点:完全放弃缓存优势,每次查询都发起网络请求,影响性能。
2. 手动更新缓存
在删除子记录的Mutation完成后,直接修改缓存中的Client对象,将clientServices设为空数组:
const [deleteService] = useMutation(DELETE_CLIENT_SERVICE_MUTATION, { update(cache) { // 读取缓存中的Client数据 const cachedClient = cache.readFragment({ id: `Client:${targetClientId}`, fragment: gql` fragment ClientServicesFragment on Client { clientServices { id __typename } } ` }); if (cachedClient) { // 写入更新后的空数组 cache.writeFragment({ id: `Client:${targetClientId}`, fragment: gql` fragment UpdatedClientServices on Client { clientServices } `, data: { ...cachedClient, clientServices: [] } }); } } });
缺点:需要手动维护缓存更新逻辑,业务场景复杂时容易出现遗漏或错误,增加维护成本。
推荐方案:自定义合并函数
如果业务中频繁出现数组清空的场景,推荐直接定义自定义合并函数,一劳永逸解决问题:
const cache = new InMemoryCache({ typePolicies: { Client: { fields: { clientServices: { merge(existing, incoming) { // 直接用incoming替换existing,包含空数组场景 return incoming; } } } } } });
内容的提问来源于stack exchange,提问作者Bob Glass
相关产品推荐
相关产品推荐

