You need to enable JavaScript to run this app. Apollo Client调用Add接口时refetchQueries重复触发两次问题求解
优惠活动
大模型
产品
解决方案
定价
更多

Apollo Client调用Add接口时refetchQueries重复触发两次问题求解

Apollo Client Mutation中refetchQueries重复执行解决方案

触发原因

该问题在搭配graphql@15.5.0使用旧版Apollo Client时非常常见,核心触发原因包括三个:

  • refetchQueries配置直接写在useMutation入参中,组件重渲染时配置引用更新导致重复注册触发
  • refetchQueries内的variables每次渲染生成新对象,引用不稳定被Apollo识别为不同查询
  • 页面内存在多个相同Query的useQuery订阅,refetchQueries默认触发所有匹配查询的重拉

可行解决方案

方案1:将refetchQueries移入mutation触发参数

不要把refetchQueries写在useMutation的初始化配置里,改为调用mutation方法时动态传入,避免重渲染导致的重复注册:

const [Add, { loading: applyLoad }] = useMutation(APPLY, {
    onCompleted(data) {
      // 原有业务逻辑
    },
    onError(error) {
      message.error(error.message);
    },
    awaitRefetchQueries: true,
});

// 触发新增操作的函数
const handleSubmit = async (formData) => {
  await Add({
    variables: formData,
    refetchQueries: [
      {
        query: ACTIVITIES_Y,
        variables: { sortBy: 'date' },
      },
      {
        query: ACTIVITIES_X,
        variables: { sortBy: 'date' },
      },
    ]
  })
}

方案2:稳定refetchQueries的引用

如果需要保留useMutation内的refetchQueries配置,用useMemo包裹配置项避免引用频繁更新:

import { useMemo } from 'react'

// 稳定refetchQueries的引用
const refetchQueries = useMemo(() => [
  {
    query: ACTIVITIES_Y,
    variables: { sortBy: 'date' },
  },
  {
    query: ACTIVITIES_X,
    variables: { sortBy: 'date' },
  },
], [])

const [Add, { loading: applyLoad }] = useMutation(APPLY, {
    onCompleted(data) {
      // 原有业务逻辑
    },
    onError(error) {
      message.error(error.message);
    },
    awaitRefetchQueries: true,
    refetchQueries
});

方案3:用update手动更新缓存(最优解)

完全放弃refetchQueries,通过mutation的update方法直接修改Apollo缓存,既不会产生额外请求,也完全避免重复触发问题,性能更好:

const [Add, { loading: applyLoad }] = useMutation(APPLY, {
    onCompleted(data) {
      // 原有业务逻辑
    },
    onError(error) {
      message.error(error.message);
    },
    update(cache, { data: addResult }) {
      // 读取ACTIVITIES_Y的现有缓存
      const yData = cache.readQuery({
        query: ACTIVITIES_Y,
        variables: { sortBy: 'date' }
      })
      // 更新后写入缓存
      cache.writeQuery({
        query: ACTIVITIES_Y,
        variables: { sortBy: 'date' },
        data: {
          activitiesY: [...yData.activitiesY, addResult.newActivity]
        }
      })
      // 同理更新ACTIVITIES_X的缓存
      const xData = cache.readQuery({
        query: ACTIVITIES_X,
        variables: { sortBy: 'date' }
      })
      cache.writeQuery({
        query: ACTIVITIES_X,
        variables: { sortBy: 'date' },
        data: {
          activitiesX: [...xData.activitiesX, addResult.newActivity]
        }
      })
    }
});

临时兼容方案

如果不想改动现有逻辑,可以在useMutation配置中新增notifyOnNetworkStatusChange: false,该配置可以解决旧版本Apollo Client的重复触发bug:

const [Add, { loading: applyLoad }] = useMutation(APPLY, {
    onCompleted(data) {
      // 原有业务逻辑
    },
    onError(error) {
      message.error(error.message);
    },
    awaitRefetchQueries: true,
    notifyOnNetworkStatusChange: false, // 新增该行
    refetchQueries: [
      {
        query: ACTIVITIES_Y,
        variables: { sortBy: 'date' },
      },
      {
        query: ACTIVITIES_X,
        variables: { sortBy: 'date' },
      },
    ],
});

内容的提问来源于stack exchange,提问作者VIKASH GUPTA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 06:18:01