urql中Mutation无法更新Graphcache缓存条目问题排查
问题排查与解决方案
针对你遇到的currentRoutine缓存未更新新创建的ProductUsage问题,从以下几个方向逐一排查:
1. 先确认解析器转换后的实体识别问题
你的Routine.productUsages解析器将嵌套结构{productUsage: {...}}转换为直接的ProductUsage对象,这里需要确保两个关键点:
- 转换后的每个对象必须包含
id和__typename: 'ProductUsage'字段(Graphcache依赖这两个字段唯一识别实体)。可以在urql DevTools中查看初始查询返回的productUsages条目,确认每个对象都有这两个字段。 - 检查服务器返回的原始嵌套数据中,
productUsage对象是否已经包含__typename,如果没有,需要在解析器中手动添加:async productUsages(parent) { return parent.productUsages.map( (item) => ({ ...item.productUsage, __typename: 'ProductUsage' }) ); }
2. 多对多关系的缓存不会自动更新
Graphcache无法自动推断多对多关系的关联更新,必须手动在Mutation中添加缓存更新逻辑。你需要在执行createProductUsageInfo Mutation时,显式将新创建的ProductUsage关联到对应的Routine实体上。
方案一:直接更新查询缓存
const [createProductUsage] = useMutation(CREATE_PRODUCT_INFO_MUTATION, { update: (cache, result) => { const newUsage = result.data.createProductUsageInfo; // 从组件上下文获取当前的ownerId和routineId const { ownerId, routineId } = useContext(/* 你的上下文 */); // 读取当前缓存的currentRoutine数据 const cachedData = cache.readQuery({ query: ROUTINE_QUERY, variables: { ownerId, routineId }, }); if (!cachedData?.currentRoutine) return; // 写入更新后的缓存 cache.writeQuery({ query: ROUTINE_QUERY, variables: { ownerId, routineId }, data: { ...cachedData, currentRoutine: { ...cachedData.currentRoutine, productUsages: [ ...cachedData.currentRoutine.productUsages, // 确保字段与ROUTINE_QUERY中查询的productUsages字段匹配 { id: newUsage.id, productId: /* 从Mutation输入或其他渠道获取 */, name: /* 同上 */, brand: /* 同上 */, category: /* 同上 */, frequency: newUsage.weeklyFrequency || newUsage.dailyFrequency, rating: newUsage.rating, __typename: 'ProductUsage', }, ], }, }, }); }, });
方案二:更新实体关联(更简洁)
如果只需要维护实体间的关联,不需要同步所有字段,可以直接更新Routine实体的productUsages数组:
const [createProductUsage] = useMutation(CREATE_PRODUCT_INFO_MUTATION, { update: (cache, result) => { const newUsage = result.data.createProductUsageInfo; const currentRoutineId = /* 从Mutation输入input.routineId或查询变量中获取 */; // 更新Routine实体的productUsages关联 cache.updateEntity( { __typename: 'Routine', id: currentRoutineId }, (routine) => { if (!routine) return routine; return { ...routine, productUsages: [ ...(routine.productUsages || []), { __typename: 'ProductUsage', id: newUsage.id }, ], }; } ); }, });
3. 验证Mutation返回的关联数据
确保你的createProductUsageInfo Mutation返回的routines数组中,包含当前操作的Routine的id。例如:
mutation createProductUsageInfo($input: CreateProductUsageInfoInput) { createProductUsageInfo(input: $input) { id # ...其他字段 routines { id __typename # 可选,但建议加上帮助Graphcache识别 } } }
这能确保Graphcache正确建立ProductUsage与Routine的双向关联。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

