React Query useInfiniteQuery 自定义全量分页拉取异常问题求助
问题根因
- 自定义Hook函数体每次组件重渲染、React Query缓存更新、预加载触发时都会重新执行,在外层定义的可变变量
page = 1不会跨渲染、跨请求持久存在,属于无稳定引用的临时闭包变量,直接导致页码计数随机错乱,出现控制台打印页码跳变的问题。 getNextPageParam的判断逻辑完全依赖上述不稳定的page变量:当page变量的计数和实际已拉取的分页进度脱节时,会永远命中“总页数大于当前自增page值”的判断,持续返回下一页参数,最终导致hasNextPage始终为true,无法在最后一页停止拉取。
修复方案
- 完全移除外层自行维护的
page变量,所有分页页码的流转全部交给React Query内置的pageParam机制管理,不需要开发者手动维护计数。 - 重写
getNextPageParam逻辑,利用该回调内置提供的allPageParams入参(即之前所有请求使用过的页码参数数组)计算下一页页码,从根源上避免计数不同步的问题。
修复后的完整自定义Hook代码
export const useGetAllContactUsRequest = ( limit = 10, unread = false ): UseInfiniteQueryResult<GetAllContactUsRequestResponse, AxiosError> => { return useInfiniteQuery( ["getAllContactUsRequest", unread], // 第一页默认传1即可,后续页码由getNextPageParam自动传入 ({ pageParam = 1 }) => getAllContactUsRequest(pageParam, limit, unread), { refetchOnWindowFocus: false, getNextPageParam: (lastPage, _allPages, allPageParams) => { // 获取当前已拉取的最后一页的页码 const currentFetchedPage = allPageParams.at(-1) ?? 1 // 已拉取页码达到后端返回的总页数时,返回undefined表示无下一页 return currentFetchedPage >= lastPage.totalPages ? undefined : currentFetchedPage + 1 }, } ); };
额外使用提示
- 消费Hook拿到分页聚合数据后,可通过
readList.pages遍历所有已拉取页的响应,结合后端返回的list为对象结构的特点,用Object.values(page.list)提取单页列表数据,最终聚合得到全量列表:const fullContactList = readList?.pages.flatMap(page => Object.values(page.list)) ?? [] - 原有滚动加载的逻辑不需要改动,当已拉取页码达到后端返回的总页数时,
getNextPageParam会返回undefined,对应的hasNextPage会自动变为false,滚动触发的加载逻辑会自然停止拉取。
内容的提问来源于stack exchange,提问作者vikky
相关产品推荐
相关产品推荐

