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

如何使用React Query useInfiniteQuery实现本地JSON数据的无限滚动

基于React Query useInfiniteQuery 实现本地JSON数据无限滚动

核心思路是利用useInfiniteQuery的自定义查询逻辑,不需要在查询函数中发起网络请求,直接对本地JSON数据做分页切片即可实现需求。

前置配置

首先准备好本地JSON数据,引入到组件中,同时定义单页展示的条目数量,示例中设定为每页10条:

// 引入本地JSON数据
import localMockData from './your-local-data.json'
// 单页展示条数,可根据需求调整
const PAGE_SIZE = 10

核心useInfiniteQuery配置

useInfiniteQuery的查询函数直接根据分页参数对本地数组做切片,同时通过getNextPageParam判断是否存在下一页数据:

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

function InfiniteList() {
  const {
    data, // 所有分页数据集合
    fetchNextPage, // 加载下一页的触发方法
    hasNextPage, // 是否存在下一页数据
    isFetchingNextPage, // 下一页是否正在加载中
  } = useInfiniteQuery({
    queryKey: ['local-infinite-list'], // 缓存唯一标识
    queryFn: ({ pageParam = 0 }) => {
      // 计算当前页切片的起止索引
      const startIndex = pageParam * PAGE_SIZE
      const endIndex = startIndex + PAGE_SIZE
      // 直接返回本地数据的切片结果,无任何网络请求
      return {
        pageData: localMockData.slice(startIndex, endIndex),
        // 标记下一页的分页参数,没有下一页则返回undefined
        nextPage: endIndex < localMockData.length ? pageParam + 1 : undefined
      }
    },
    // 提取下一页分页参数
    getNextPageParam: (lastPage) => lastPage.nextPage,
    // 可选配置:关闭数据 stale 时间,本地数据不需要重新校验
    staleTime: Infinity,
  })

  // 合并所有分页数据用于渲染
  const renderList = data?.pages.flatMap(page => page.pageData) || []

  // 滚动到底部触发加载更多,也可替换为IntersectionObserver实现
  const handleScroll = (e) => {
    const { scrollTop, scrollHeight, clientHeight } = e.target
    const isReachBottom = scrollTop + clientHeight >= scrollHeight - 20 // 预留20px提前触发
    if (isReachBottom && hasNextPage && !isFetchingNextPage) {
      fetchNextPage()
    }
  }

  return (
    <div 
      style={{ height: '70vh', overflowY: 'auto' }}
      onScroll={handleScroll}
    >
      {/* 渲染列表 */}
      {renderList.map((item, idx) => (
        <div key={idx} style={{ padding: '16px', borderBottom: '1px solid #f0f0f0' }}>
          {item.content}
        </div>
      ))}

      {/* 加载状态提示 */}
      {isFetchingNextPage && <div style={{ padding: '12px', textAlign: 'center' }}>加载中...</div>}
      {/* 无更多数据提示 */}
      {!hasNextPage && renderList.length > 0 && <div style={{ padding: '12px', textAlign: 'center', color: '#999' }}>已加载全部数据</div>}
    </div>
  )
}

注意事项

  • 如果本地数据量级较大(超过1000条),建议配合虚拟滚动组件使用,避免DOM节点过多导致页面卡顿
  • 滚动触发逻辑可替换为IntersectionObserver实现,性能更优,只需要在列表底部放置一个观测元素,元素进入视口时触发fetchNextPage即可
  • 本地数据不会发生变更的情况下,可以将staleTime设置为Infinity,避免React Query触发不必要的重新查询

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:51:03