使用 useInfiniteQuery 实现无限滚动与分页
获取分页数据,并使用 useInfiniteQuery 无缝加载更多页面。
使用 useInfiniteQuery 实现无限滚动与分页 是 CoddyKit 上的免费 React Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
欢迎
在本课中,您将使用 useInfiniteQuery 获取分页数据,并实现无限滚动模式,让用户滚动时加载更多页面。
什么是 useInfiniteQuery?
useInfiniteQuery 会以“页面”为单位获取数据。每个页面分别获取,并追加到缓存列表中。它提供 fetchNextPage、hasNextPage 和 isFetchingNextPage 等实用属性。
基础设置
定义 initialPageParam 和 getNextPageParam。queryFn 会接收当前的 pageParam,并且必须返回一页结果。
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
queryKey: ['posts'],
queryFn: ({ pageParam }) =>
fetch('/api/posts?cursor=' + pageParam).then(r => r.json()),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
});getNextPageParam
getNextPageParam 会接收最后获取的页面和所有页面。请返回下一个页面游标或编号;如果没有更多页面,请返回未定义值或空值,以表示没有更多页面可用(此时 hasNextPage 会变为否)。
getNextPageParam: (lastPage, allPages) => {
return lastPage.hasMore ? lastPage.nextCursor : undefined;
}渲染所有页面
data.pages 是页面结果组成的数组。请将其展平,以便将所有项目渲染为连续列表。
const allPosts = data.pages.flatMap(page => page.items);
return (
<ul>
{allPosts.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
);加载更多按钮
添加一个“加载更多”按钮来调用 fetchNextPage。当没有更多页面或正在获取数据时,请禁用该按钮。
<button
onClick={() => fetchNextPage()}
disabled={!hasNextPage || isFetchingNextPage}
>
{isFetchingNextPage ? 'Loading...' : hasNextPage ? 'Load More' : 'No more posts'}
</button>使用 IntersectionObserver 实现无限滚动
将 IntersectionObserver 附加到列表底部的哨兵元素上。当它进入视口时,自动调用 fetchNextPage。
const observerRef = useRef();
useEffect(() => {
const observer = new IntersectionObserver(entries => {
if (entries[0].isIntersecting && hasNextPage) fetchNextPage();
});
if (observerRef.current) observer.observe(observerRef.current);
return () => observer.disconnect();
}, [hasNextPage, fetchNextPage]);
<div ref={observerRef} /> {/* sentinel at bottom */}双向无限滚动
对于聊天应用,请支持双向滚动:使用 fetchNextPage 获取较早的消息,使用 getPreviousPageParam/fetchPreviousPage 获取较新的消息。
基于页码与基于游标的分页
基于偏移量或页码:initialPageParam=1,getNextPageParam 返回 lastPage.page + 1。基于游标:使用最后一项的 ID 作为游标。基于游标的方式对于实时数据更稳定。
// Offset-based
getNextPageParam: (lastPage) => lastPage.page + 1重新获取无限查询
对无限查询调用 invalidateQueries 只会重新获取第一页。要重新获取所有页面(例如新增帖子后),请使用 queryClient.resetQueries,或使用 refetchType: 'all'。
快速检查
要表示没有更多页面可加载,getNextPageParam 必须返回什么?
回顾
useInfiniteQuery 会将页面累积到 data.pages 中。请使用 flatMap 将其展平后进行渲染。让 getNextPageParam 返回未定义值即可停止。您可以在按钮点击时调用 fetchNextPage,或在 IntersectionObserver 触发时调用它来实现无限滚动。
课程完成
恭喜您!您已完成 **React Query:服务器状态管理**。现在,您可以使用 TanStack Query 获取、缓存、变更数据,进行分页,并实现无限滚动。
常见问题解答
「使用 useInfiniteQuery 实现无限滚动与分页」课时是免费的吗?
是的 — 「使用 useInfiniteQuery 实现无限滚动与分页」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「使用 useInfiniteQuery 实现无限滚动与分页」这节课中我会学到什么?
获取分页数据,并使用 useInfiniteQuery 无缝加载更多页面。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「使用 useInfiniteQuery 实现无限滚动与分页」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 设置 React Query 与 QueryClient
- 缓存、过期时间与后台重新获取
- 使用 useMutation 执行变更
- 使用 useInfiniteQuery 实现无限滚动与分页