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

react-query useInfiniteQuery分页异常求助:pageIndex不递增致数据重复

React Query useInfiniteQuery pageIndex 始终为0 导致数据重复的解决方案

问题原因分析

你的代码存在两个关键问题,导致pageIndex无法正常递增:

  1. fetchPosts参数传递错误:
    fetchPosts定义的参数是(key, pageIndex = 0),但在useInfiniteQuery的查询函数中,你只传递了pageIndex作为第一个参数,导致fetchPosts内部的pageIndex始终取默认值0。

  2. 查询函数参数与调用不匹配:
    useInfiniteQuery的查询函数接收包含pageIndex的对象,但调用fetchPosts时未正确传递key参数,使得参数顺序错乱,最终offset一直为0*10=0,每次都重复获取前10条数据。

解决方案

步骤1:修正参数传递逻辑

你可以直接优化fetchPosts,去掉未使用的key参数,让它只接收pageIndex:

const fetchPosts = async (pageIndex = 0) => {
  const offset = pageIndex * PAGE_LIMIT;
  try {
    const { data } = await axios.get(`/posts`, {
      params: { offset: offset, limit: PAGE_LIMIT },
    });
    return data;
  } catch (err) {
    console.log(err);
  }
};

步骤2:确保查询函数正确传参

在useInfiniteQuery中,直接将解构出的pageIndex传给fetchPosts:

useInfiniteQuery("/posts", ({ pageIndex = 0 }) => fetchPosts(pageIndex), {
  getNextPageParam: (lastPage, allPages) => {
    return lastPage.length ? allPages.length : undefined;
  },
});

你的getNextPageParam逻辑是正确的:当最后一页有数据时,返回allPages.length作为下一页的pageIndex,确保下一次请求的offset是正确的分页起始值。

修改后的完整前端代码

import React from "react";
import { useRef, useCallback} from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { useInfiniteQuery } from "react-query";

const PAGE_LIMIT = 10;

const fetchPosts = async (pageIndex = 0) => {
  const offset = pageIndex * PAGE_LIMIT;
  try {
    const { data } = await axios.get(`/posts`, {
      params: { offset: offset, limit: PAGE_LIMIT },
    });
    return data;
  } catch (err) {
    console.log(err);
  }
};

const Home = () => {
  const {
    fetchNextPage,
    hasNextPage, 
    isFetchingNextPage, 
    data,
    status,
    error,
  } = useInfiniteQuery("/posts", ({ pageIndex = 0 }) => fetchPosts(pageIndex), {
    getNextPageParam: (lastPage, allPages) => {
      return lastPage.length ? allPages.length : undefined;
    },
  });

  const intObserver = useRef();
  const lastPostRef = useCallback(
    (post) => {
      if (isFetchingNextPage) return;

      if (intObserver.current) intObserver.current.disconnect();

      intObserver.current = new IntersectionObserver((posts) => {
        if (posts[0].isIntersecting && hasNextPage) {
          console.log("We are near the last post!");
          fetchNextPage();
        }
      });

      if (post) intObserver.current.observe(post);
    },
    [isFetchingNextPage, fetchNextPage, hasNextPage]
  );

  if (status === "error")
    return <p className="center">Error: {error.message}</p>;

  const content = data?.pages.map((pg) => {
    return pg.map((post, i) => {
      if (pg.length === i + 1) {
        return (
          <Link ref={lastPostRef} className="link" to={`/post/${post.id}`}>
            <div className="post" key={post.id}>
              <p> {post.title}</p>
              <p> {post.content}</p>
            </div>
          </Link>
        );
      }
      return (
        <Link className="link" to={`/post/${post.id}`}>
          <div className="post" key={post.id}>
            <p> {post.title}</p>
            <p> {post.content}</p>
          </div>
        </Link>
      );
    });
  });

  return (
    <div>
      <div className="home">
        <div className="container">
          <div className="posts">
            {content}
            {isFetchingNextPage && (
              <p className="center">Loading More Posts...</p>
            )}
            <p className="center">
              <a href="#top">Back to Top</a>
            </p>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Home;

验证效果

修改完成后,后端控制台打印的offset会依次为0、10、20...,每次请求都会获取新的分页数据,不会出现重复内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 17:55:42