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

React Query useInfiniteQuery旧数据被覆盖、hasNextPage为undefined问题

问题根因

1. queryKey配置错误

你当前把page、start这类分页动态参数放到了queryKey中,每次翻页时queryKey会发生变化,React Query会将其识别为全新的查询,直接用新查询的结果覆盖原有数据,不会合并到pages数组中。

2. 请求函数未正确使用pageParam

如果你的getVendors函数没有使用useInfiniteQuery注入的pageParam作为分页参数,而是直接使用外部的start/thisPage变量,也会导致分页逻辑异常,数据被覆盖。

3. 冗余配置干扰

keepPreviousData是普通useQuery用于切换查询时保留上一次数据的配置,在useInfiniteQuery中不需要配置,反而可能干扰内部的分页数据合并逻辑。

修复方案

第一步:修正queryKey

仅保留和筛选相关的静态参数,移除所有分页相关的动态参数:

const { 
  data, 
  status, 
  error, 
  isSuccess, 
  hasNextPage,
  fetchNextPage, 
  isFetching,
  isFetchingNextPage, 
  isLoading,
  isError,
} = useInfiniteQuery(
  [
    'vendors',
    {vendor_type: vendorTypesId}, 
    {country: countryId}, 
    {city: cityId}, 
    {vendor_product_types: productCategoryId}, 
    {name: nameInput},
    {limit: limit},
  ],
  getVendors, 
  { 
    initialData: {
      pages : [{
        result: vendors,
        resultCount: 495,
        nextPageId: 15
      }], 
      pageParams: [0] // 初始分页参数对应第一页的start值
    },
    getNextPageParam: (lastPage) => lastPage.nextPageId
  }
) 

第二步:修正getVendors请求函数

从useInfiniteQuery传入的上下文参数中获取pageParam作为start参数,不要使用外部的分页变量:

const getVendors = async ({ pageParam = 0 }) => {
  // 调用后端接口时,用pageParam作为start参数
  const response = await fetch('/你的后端接口', {
    method: 'GET',
    params: {
      vendor_type: vendorTypesId,
      country: countryId,
      city: cityId,
      vendor_product_types: productCategoryId,
      name: nameInput,
      limit: limit,
      start: pageParam
    }
  })
  const resData = await response.json()
  // 自动判断是否存在下一页,返回undefined时hasNextPage会自动变为false
  const nextPageId = resData.result.length < limit ? undefined : pageParam + limit
  return {
    result: resData.result,
    resultCount: resData.resultCount,
    nextPageId: nextPageId
  }
}

第三步:正确渲染分页数据

需要合并所有页的结果进行渲染,不要只取单页数据:

// 合并所有页的商家数据
const vendorList = data?.pages.flatMap(page => page.result) || []

// 渲染示例
return (
  <div>
    {vendorList.map(vendor => <div key={vendor.id}>{vendor.name}</div>)}
    {hasNextPage && (
      <button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
        {isFetchingNextPage ? '加载中...' : '加载更多'}
      </button>
    )}
  </div>
)

可选补充:筛选条件变化时重置分页

如果筛选条件变更后需要回到第一页,可以监听筛选参数变化,调用重置方法:

const queryClient = useQueryClient()
useEffect(() => {
  // 当筛选参数变化时重置分页查询
  queryClient.resetQueries(['vendors'])
}, [vendorTypesId, countryId, cityId, productCategoryId, nameInput, limit])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 03:36:03