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

Apollo GraphQL中执行Mutation后如何重新获取所有查询?

Apollo GraphQL更新Person后缓存不一致的解决办法

方法1:手动修改归一化缓存

Apollo的缓存是归一化的,每个对象通过__typename+id唯一标识。只要直接修改缓存中对应Person对象的字段,所有引用该对象的查询都会自动同步更新,不用逐个刷新查询。

修改你的useMutation调用,添加update函数:

const [updatePerson] = useMutation(UPDATE_PERSON, {
  update(cache, { data: { updateOnePerson } }, { variables }) {
    // 拿到本次更新的字段数据
    const newPersonFields = variables.person;
    // 生成缓存中该Person对象的唯一标识
    const personCacheId = cache.identify({ __typename: 'Person', id: updateOnePerson.id });

    // 修改缓存中对应字段
    cache.modify({
      id: personCacheId,
      fields: {
        name() { return newPersonFields.name; },
        age() { return newPersonFields.age; },
        height() { return newPersonFields.height; },
        weight() { return newPersonFields.weight; }
        // 其他需要更新的字段同理添加
      }
    });
  }
});

这样不管是PERSON_DATA(直接查询单个Person)还是PERSON_NAMES(Family下的Person列表),只要引用了这个Person对象,都会自动获取更新后的值。

方法2:配置全局类型策略(推荐)

提前在Apollo Client初始化时配置typePolicies,让Apollo自动处理缓存合并,不用每次写mutation都手动维护缓存。

  1. 先修改Mutation的返回值,返回更新后的完整字段(而不只是id):
export const UPDATE_PERSON = graphql(`
  mutation updatePerson($personId: String!, $person: PersonUpdateInput!) {
    updateOnePerson(query: { id: $personId }, set: $person) {
      id
      name
      age
      height
      weight
    }
  }
`)
  1. 在创建ApolloClient时添加类型策略:
import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: '/your-graphql-endpoint',
  cache: new InMemoryCache({
    typePolicies: {
      Person: {
        fields: {
          // 配置字段合并规则:新值优先,没有新值则保留旧值
          name: { merge: (existing, incoming) => incoming ?? existing },
          age: { merge: (existing, incoming) => incoming ?? existing },
          height: { merge: (existing, incoming) => incoming ?? existing },
          weight: { merge: (existing, incoming) => incoming ?? existing }
        }
      },
      Family: {
        fields: {
          // 处理Family下的Persons列表,用id匹配合并
          persons: {
            merge(existing = [], incoming) {
              const mergedList = [...existing];
              incoming.forEach(newPerson => {
                const matchIndex = mergedList.findIndex(p => p.id === newPerson.id);
                if (matchIndex !== -1) {
                  mergedList[matchIndex] = { ...mergedList[matchIndex], ...newPerson };
                } else {
                  mergedList.push(newPerson);
                }
              });
              return mergedList;
            }
          }
        }
      }
    }
  })
});

配置完成后,每次执行UPDATE_PERSON mutation,Apollo会自动把返回的Person数据合并到缓存中,所有相关查询都会自动更新,无需额外代码。

方法3:动态筛选要刷新的查询

如果偏好使用refetchQueries,可以用函数形式动态筛选当前缓存中与Person相关的查询,避免手动维护查询列表:

const [updatePerson] = useMutation(UPDATE_PERSON, {
  refetchQueries: ({ queryManager }) => {
    // 获取缓存中所有活跃的查询
    const allQueries = queryManager.getCache().getAllQueries();
    // 筛选出名称包含Person的查询(可根据实际情况调整筛选规则)
    return allQueries
      .filter(query => {
        const opDef = query.query.definitions.find(def => def.kind === 'OperationDefinition');
        return opDef?.name?.value.toLowerCase().includes('person');
      })
      .map(query => ({ query: query.query, variables: query.variables }));
  }
});

这种方法会自动刷新所有相关查询,但可能会带来不必要的网络请求,性能上不如前两种方法。


内容的提问来源于stack exchange,提问作者Simon Tran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:02:45