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

React Query实现无限滚动时如何拼接旧数据与新加载数据

问题原因

你当前的实现无法累加数据的核心原因是:每次页码变化时,useQuery的queryKey[ACTIVITY_FEED, activityFeedPageIndex]会同步变化,React Query会将不同页码识别为独立的查询请求,各自维护独立缓存。而select方法只能访问当前单次请求返回的响应数据,无法跨查询拿到之前页码的旧缓存,自然没法直接完成数据拼接。

推荐实现(官方标准方案)

无限滚动场景优先使用React Query官方提供的useInfiniteQueryHook,它原生支持多页数据缓存、累加逻辑,不需要手动处理旧数据获取:

const useActivityFeedData = (pageSize = Config.defaultPageSize) =>
  useInfiniteQuery(
    [ACTIVITY_FEED],
    ({ pageParam = 1 }) => Api.user.getActivityFeedData(pageParam, pageSize),
    {
      initialData: {
        pages: [{ activityList: [] }],
        pageParams: [1],
      },
      // 计算下一页请求的页码
      getNextPageParam: (lastPage, allPages) => {
        // 按实际接口逻辑调整:当前页返回数据不足pageSize时说明没有更多数据
        if (lastPage.activityList.length < pageSize) return undefined;
        return allPages.length + 1;
      },
      select: (data) => ({
        // 拍平所有分页数据得到累加后的完整列表
        activityList: data.pages.flatMap(page => page.activityList),
        pageParams: data.pageParams
      }),
    }
  );

调用方式

  • 不需要在外部维护页码状态,Hook内部会自动管理分页参数
  • 从返回结果中取activityList即可拿到累加后的全量列表
  • 滚动到底部触发加载时,直接调用返回的fetchNextPage方法拉取下一页
  • 可通过返回的hasNextPage判断是否还有剩余数据,isFetchingNextPage判断下一页加载状态,避免重复发起请求
兼容原有useQuery写法的实现

如果你不想替换为useInfiniteQuery,可以通过queryClient手动获取上一页缓存完成拼接,注意这种方式仅支持连续页码的线性加载,跳页、缓存回收都会导致数据断层:

import { useQueryClient } from '@tanstack/react-query';

const useActivityFeedData = (
  activityFeedPageIndex: number,
  pageSize = Config.defaultPageSize,
) => {
  const queryClient = useQueryClient();
  return useQuery(
    [ACTIVITY_FEED, activityFeedPageIndex],
    () => Api.user.getActivityFeedData(activityFeedPageIndex, pageSize),
    {
      initialData: {
        activityList: [],
      },
      keepPreviousData: true,
      select: (res: any) => {
        // 第一页直接返回当前数据
        if (activityFeedPageIndex === 1) {
          return { activityList: res.activityList };
        }
        // 读取上一页的缓存数据
        const prevPageCache = queryClient.getQueryData<{activityList: any[]}>([
          ACTIVITY_FEED,
          activityFeedPageIndex - 1
        ]);
        // 拼接新旧数据返回
        return {
          activityList: [...(prevPageCache?.activityList || []), ...res.activityList]
        };
      },
    },
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 03:31:01