如何向携带pageParam的useInfiniteQuery传递filters变量
useInfiniteQuery 同步传递filters与pageParam问题修复
问题对应根因
你遇到的两个问题都是代码逻辑疏漏导致的:
- 无法正常获取分页数据:
queryFn没有接收useInfiniteQuery自动注入的pageParam上下文,调用fetchInfiniteVariants时仅传了filters,漏传分页参数,除了第一页默认值0之外,后续翻页的偏移量完全没有传入请求;同时getNextPageParam读取的lastPage.data.offset是你发请求时传的参数,除非接口主动在响应体返回该字段,否则这个值为undefined,会直接判定没有下一页,终止分页加载。 - 数据重复渲染:
getNextPageParam返回值逻辑错误,没有基于已加载数据量计算下一页偏移,若接口意外返回了请求传入的offset值,会导致每次加载更多都请求同一偏移地址,拿到重复数据触发重复渲染。 - 额外冗余问题:自定义hook入参定义了
offset但完全没有使用,和内部维护的分页状态冲突;传入的filters如果是父组件每次渲染新建的对象,会导致queryKey频繁变更,触发不必要的查询重置。
正确实现方式
核心修复点
queryFn必须接收上下文对象,取出内部维护的pageParam传给请求函数getNextPageParam基于已加载的总数据量计算下一页偏移,同时判断终止条件(单页返回数据量小于pageSize时返回undefined,代表没有更多数据)- 移除无用的自定义
offset入参,分页参数完全由useInfiniteQuery内部管理 - 若需要使用首屏初始数据,正确配置
initialData结构
修正后完整代码
export const fetchInfiniteVariants = async ( filters = {}, { pageParam = 0 } ) => { const records = await axios.get(baseURL, { headers: authHeader, params: { pageSize: 24, offset: pageParam, fields: [ "name", "packshot", "packshot_size", "brand_logo", "price", "slug", ], filterByFormula: `(${filterByFields(filters)})`, "sort[0][field]": "priority", "sort[0][direction]": "asc", }, }) return records } export const useInfiniteVariantsQuery = ( initialRecords, filters = { brand: "HAY" } ) => { const infiniteVariantsQuery = useInfiniteQuery( ["infiniteVariants", filters], // 接收queryFn注入的pageParam,传入请求函数 ({ pageParam = 0 }) => fetchInfiniteVariants(filters, { pageParam }), { initialStale: true, staleTime: 6000, getNextPageParam: (lastPage, allPages) => { // 注意:将records替换为你接口实际返回的列表字段名 const currentPageList = lastPage.data.records // 单页返回数据不足24条,说明已到最后一页,终止加载 if (currentPageList.length < 24) return undefined // 下一页偏移量 = 所有已加载页的总条目数 return allPages.flatMap(page => page.data.records).length }, // 首屏初始数据配置,不需要可删除 initialData: initialRecords ? { pages: [initialRecords], pageParams: [0] } : undefined } ) return infiniteVariantsQuery }
使用注意事项
- 传入hook的
filters参数请保持引用稳定,在父组件中用useMemo包裹,避免每次渲染新建对象导致queryKey变化,触发表单重置重新拉取 - 切换筛选条件时不需要手动重置分页,queryKey包含filters,筛选值变化后React Query会自动从第一页重新加载数据
- 不要自行维护offset分页状态,所有分页逻辑交给useInfiniteQuery内部处理,避免状态冲突。
内容的提问来源于stack exchange,提问作者Ian Tran
相关产品推荐
相关产品推荐

