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
相关产品推荐
相关产品推荐

