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

如何用React Query实现无限滚动(API仅返回hasNextPage标识)

用React Query实现基于hasNextPage的无限滚动(滚动到底部自动加载)

核心思路

React Query的useInfiniteQuery是处理无限滚动的适配工具,结合你的API返回的hasNextPage字段,无需总页数或总数据量,就能精准控制下一页加载逻辑。

步骤1:配置useInfiniteQuery

先定义API请求函数,再用useInfiniteQuery完成查询配置:

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

// 定义API请求函数,接收当前页码参数
const fetchEvents = async ({ pageParam = 1 }) => {
  const response = await fetch(`/api/events?page=${pageParam}`);
  const data = await response.json();
  return data; // 对应API返回结构:{ events: Event[], hasNextPage: boolean }
};

function EventList() {
  const {
    data,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    status,
    error,
  } = useInfiniteQuery({
    queryKey: ['events'], // 唯一标识查询的键
    queryFn: fetchEvents,
    // 关键逻辑:根据上一页的hasNextPage判断是否触发下一页
    getNextPageParam: (lastPage, allPages) => {
      if (lastPage.hasNextPage) {
        return allPages.length + 1; // 已加载n页,下一页为n+1(页码从1开始)
      }
      return undefined; // 返回undefined表示没有下一页
    },
    initialPageParam: 1, // 初始页码设为1
  });

步骤2:添加滚动监听逻辑

通过useEffect监听窗口滚动,当滚动接近底部时自动触发下一页加载:

useEffect(() => {
    const handleScroll = () => {
      // 判断是否滚动到接近底部(200px阈值,可根据体验调整)
      const isNearBottom = window.innerHeight + document.documentElement.scrollTop >= 
        document.documentElement.offsetHeight - 200;
      
      // 满足条件才触发:有下一页、当前未在加载下一页、滚动到阈值区域
      if (isNearBottom && hasNextPage && !isFetchingNextPage) {
        fetchNextPage();
      }
    };

    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, [hasNextPage, isFetchingNextPage, fetchNextPage]);

步骤3:渲染数据与状态

合并所有页面的events数据,渲染列表并展示加载/无更多数据状态:

// 合并所有页面的events数组
  const allEvents = data?.pages.flatMap(page => page.events) || [];

  if (status === 'loading') return <div>加载中...</div>;
  if (status === 'error') return <div>加载失败:{error.message}</div>;

  return (
    <div>
      <ul>
        {allEvents.map(event => (
          <li key={event.id}>{event.title}</li> // 根据你的event结构调整渲染内容
        ))}
      </ul>
      
      {/* 下一页加载状态提示 */}
      {isFetchingNextPage && <div>加载更多...</div>}
      
      {/* 无更多数据时的提示 */}
      {!hasNextPage && allEvents.length > 0 && <div>已加载全部数据</div>}
    </div>
  );
}

export default EventList;

关键细节说明

  • getNextPageParam:利用已加载页面数量计算下一页页码,完全适配你的API页码递增逻辑,无需额外参数。
  • 滚动阈值:设置提前加载的阈值,避免用户滚动到底部才开始加载,提升流畅度。
  • 重复请求拦截:通过isFetchingNextPage判断当前是否在加载下一页,防止重复触发请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:40:16