Apollo Client为何自发将缓存对象部分属性设为null?
Apollo Client 3.7.3 缓存中可选字段被自动置为null的问题处理
问题现象
在React.js+TypeScript项目中使用@apollo/client 3.7.3版本时,遇到以下异常:
- 获取对象列表后,缓存内部分属性被自动设为
null,缓存数据与服务器返回的响应完全不一致 - 仅特定对象类型或接口调用出现该问题,且仅针对GraphQL Schema中标记为可选的字段;将这些字段改为非可选后,问题消失
已完成的排查验证
- 确认后端返回数据、客户端接收的响应内容完全正确,无字段缺失或值为null的情况
- 已隔离目标查询,排除了其他应用代码修改该缓存的可能性
- 为查询设置
fetchPolicy: "no-cache"时,功能完全正常,无字段被置为null的问题
问题原因分析
Apollo Client的Normalized Cache默认会根据GraphQL Schema的字段可选性处理缓存合并逻辑。对于标记为可选的字段,当缓存中存在该对象的历史记录时,新查询响应与缓存记录的合并过程中,Schema的可选定义可能触发默认合并行为,错误地将服务器返回的有效字段值覆盖为null。这种情况在接口类型或特定自定义对象类型的可选字段上更容易出现。
解决方案
临时规避方案
对出现问题的查询设置fetchPolicy: "network-only"或"no-cache",绕过缓存直接使用服务器响应。但此方案会失去缓存带来的性能优化,仅适合临时验证或非核心业务场景。
根本修复方案
- 调整Schema字段可选性:若业务逻辑允许,将出现问题的可选字段改为非可选类型(已验证可解决问题)
- 自定义缓存合并策略:针对出现问题的对象类型和字段,自定义缓存合并函数,强制保留服务器返回的字段值:
import { InMemoryCache } from '@apollo/client'; const cache = new InMemoryCache({ typePolicies: { // 替换为出现问题的对象类型名称 TargetObject: { fields: { // 替换为被置为null的可选字段名称 optionalField: { merge(existing, incoming) { // 优先使用新获取的字段值,不存在时再沿用旧值 return incoming ?? existing; } } } } } }); - 校验Schema一致性:确保客户端使用的GraphQL Schema与后端完全同步,避免字段可选性定义出现偏差(比如通过代码生成工具同步Schema时出现错误)
内容的提问来源于stack exchange,提问作者Ali Afsahnoudeh
相关产品推荐
相关产品推荐

