You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:35:25