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

Apollo Client递归获取Relay风格分页全量数据的问题

解决Apollo Client自动加载全部分页数据的问题

你的代码存在两个核心问题:分页参数传递错误导致重复请求同一页面,以及networkStatus判断逻辑不完整导致无法持续触发后续请求,进而出现仅两次请求且缓存有重复对象的情况。以下是修复方案:

核心问题分析

  1. 参数传递错误:初始查询的分页参数嵌套在pageArgs中,但fetchMore时直接传递了after和first,后端无法识别正确的分页条件,导致重复返回第一页数据,最终缓存出现重复条目。
  2. 请求触发逻辑缺陷:仅监听networkStatus === NetworkStatus.ready,未考虑fetchMore执行时的状态变化,同时缺少请求状态锁,可能导致重复触发或中断后续请求。

修复后的代码

import { useQuery, NetworkStatus } from '@apollo/client';
import { useEffect, useState } from 'react';

const {
  data,
  loading,
  networkStatus,
  fetchMore,
} = useCustomQuery({
  variables: {
    pageArgs: {
      first: 1, // 可根据实际需求调整每页数量
    },
  },
  notifyOnNetworkStatusChange: true,
});

const items = data?.customQuery?.edges.map((edge) => edge.node) || [];
const currentPageInfo = data?.customQuery?.pageInfo;
const nextCursor = currentPageInfo?.endCursor;
const hasNextPage = currentPageInfo?.hasNextPage;
// 添加状态锁,避免并发请求
const [isFetchingMore, setIsFetchingMore] = useState(false);

useEffect(() => {
  // 仅当:非初始加载、有下一页、当前未在请求更多数据、请求状态完成
  if (!loading && hasNextPage && !isFetchingMore && networkStatus === NetworkStatus.ready) {
    setIsFetchingMore(true);
    fetchMore({
      // 修正参数结构,与初始查询保持一致
      variables: {
        pageArgs: {
          after: nextCursor,
          first: 1,
        },
      },
      updateQuery(previousResult: CustomQuery, { fetchMoreResult }) {
        if (!fetchMoreResult?.customQuery) {
          setIsFetchingMore(false);
          return previousResult;
        }

        const mergedEdges = [
          ...previousResult.customQuery.edges,
          // 过滤重复条目,基于node的唯一id
          ...fetchMoreResult.customQuery.edges.filter(
            (newEdge) => !previousResult.customQuery.edges.some(
              (prevEdge) => prevEdge.node.id === newEdge.node.id
            )
          )
        ];

        const updatedResult = {
          ...previousResult,
          customQuery: {
            ...previousResult.customQuery,
            edges: mergedEdges,
            pageInfo: fetchMoreResult.customQuery.pageInfo,
          },
        };

        setIsFetchingMore(false);
        return updatedResult;
      },
    });
  }
}, [loading, hasNextPage, nextCursor, networkStatus, fetchMore, isFetchingMore]);

关键修改说明

  • 修正参数结构:将fetchMore的分页参数嵌套到pageArgs中,与初始查询的参数结构保持一致,确保后端能正确识别分页条件,避免重复请求同一页面。
  • 添加请求状态锁:通过isFetchingMore状态防止并发请求,避免同一时间发起多个fetchMore请求导致的逻辑混乱。
  • 优化触发条件:增加!loading和!isFetchingMore的判断,确保仅在初始加载完成且没有正在进行的请求时,才触发下一页数据获取。
  • 更新状态锁时机:在updateQuery中及时重置isFetchingMore状态,确保后续请求能正常触发。

内容的提问来源于stack exchange,提问作者coler-j

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 01:30:57