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

Apollo Client fetchMore执行后触发重复网络请求问题求助

解决Apollo React无限滚动中fetchMore重复请求及数据重复问题

以下是针对你遇到问题的具体排查和修复建议:

  • 确认fetchMore的变量传递正确性
    确保调用fetchMore时,offset参数是基于已加载数据的长度累加,而非重复使用初始值0。错误的offset会导致重复请求同一页数据,进而触发merge后的数据重复。正确的调用示例:

    fetchMore({
      variables: {
        // 基于已有数据长度计算新的offset
        offset: data?.AssetData.assets.length || 0,
        // 保持其他变量与原查询一致
        role,
        version,
        region,
        limit: 30
      },
      // 可配合updateQuery手动合并数据(与typePolicies的merge功能互补)
      updateQuery: (prevResult, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prevResult;
        return {
          ...prevResult,
          AssetData: {
            ...prevResult.AssetData,
            assets: [...prevResult.AssetData.assets, ...fetchMoreResult.AssetData.assets]
          }
        };
      }
    });
    
  • 优化typePolicies的merge逻辑
    当前merge函数直接拼接数组,未做去重处理。即使重复请求数据,也会导致缓存中出现重复项。可以在merge中加入去重逻辑:

    merge(existing = [], incoming: string[], { args }) {
      const existingItems = new Set(existing);
      // 过滤掉已存在的项
      const newItems = incoming.filter(item => !existingItems.has(item));
      return [...existing, ...newItems];
    }
    

    同时确认keyFields: []的设置是否符合你的业务场景——该配置会将所有AssetData实例视为同一缓存条目,适合单一分页列表的场景;如果存在多个独立的AssetData列表,需要设置唯一的keyFields来区分。

  • 排查useQuery的触发原因
    原查询重复发起可能是由于依赖变量(role/version/region)意外变化导致useQuery重新执行。检查这些变量的来源:

    • 确保变量是稳定的,比如用useMemo包裹避免不必要的引用变化;
    • 检查组件是否因其他props变化而重渲染,导致useQuery重复执行初始查询。
  • 调整fetchPolicy配置
    当前fetchPolicy: 'cache-and-network'会在组件挂载时同时请求缓存和网络,而nextFetchPolicy: 'cache-first'仅在后续操作优先使用缓存。但在无限滚动场景下,可尝试调整为:

    useQuery<AssetsQuery>(assetsQuery, {
      variables: { /* ... */ },
      fetchPolicy: 'cache-first', // 首次加载优先用缓存,避免重复请求
      notifyOnNetworkStatusChange: true, // 便于监听网络状态变化
    });
    

    若需要首次加载最新数据,可保留cache-and-network,但需确认缓存失效策略不会触发不必要的重新请求。

  • 排除InvalidationPolicyCache的干扰
    你使用了InvalidationPolicyCache并设置了Asset类型的TTL,可能导致缓存频繁失效,触发原查询重复请求。可以暂时替换为普通的InMemoryCache测试:

    cache: new InMemoryCache({
      typePolicies: { /* 保持原typePolicies配置 */ }
    }),
    

    如果问题消失,说明是缓存失效策略导致的,需要调整timeToLive或针对分页场景优化失效规则。

  • 监听networkStatus排查请求触发源
    开启notifyOnNetworkStatusChange: true后,打印networkStatus值,确认每次请求的触发时机:

    useEffect(() => {
      console.log('Network status:', networkStatus);
    }, [networkStatus]);
    

    Apollo的networkStatus枚举值可帮助你区分是初始查询、fetchMore请求还是缓存重新验证请求,进而定位重复请求的来源。

内容的提问来源于stack exchange,提问作者Hima Chitalia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 09:01:02