TanStack useInfiniteQuery问题:isFetching始终为true且data未定义
问题分析与解决方案
你的代码出现isFetching始终为true、data一直undefined的核心原因有两个:
1. 分页逻辑不匹配导致无限请求
useInfiniteQuery的getNextPageParam你写的是lastPage.nextCursor,但你的fetchUsers函数返回的对象里根本没有nextCursor字段——你返回的是{ resultUsers, resultPage }。这会导致getNextPageParam每次都返回undefined,而useInfiniteQuery会把undefined当成“还有下一页需要加载”,从而不断发起请求,陷入无限循环,自然data无法稳定,isFetching一直为true。
2. 类型断言掩盖了潜在错误
你用fetchUsers as any跳过了TypeScript的类型检查,这会让你无法提前发现返回类型和useInfiniteQuery泛型ResultUsers不匹配的问题,增加调试难度。
修复步骤
第一步:修正数据获取函数的返回值,补充分页判断
修改fetchUsers,让它返回明确的下一页标识,同时简化async/await写法:
interface Props { pageParam?: number; } // 定义返回类型,让TypeScript做类型检查 interface FetchUsersResponse { resultUsers: ResultUsers[]; // 确保ResultUsers是你定义的用户数组类型 currentPage: number; nextPage?: number; } export async function fetchUsers({ pageParam = 1 }: Props): Promise<FetchUsersResponse> { const seed = 'horse'; const apiLink = `https://XXXX.XX/api/?results=10&inc=email,picture,name,location&seed=${seed}&page=${pageParam}`; const response = await fetch(apiLink); if (!response.ok) throw new Error('Error when connecting to DB'); const data = await response.json(); const resultUsers = data.results.map( ({ email, picture, name, location }: Result) => ({ id: email, picture: picture.thumbnail, firstName: name.first, lastName: name.last, country: location.country, }) ); const currentPage = Number(data.info.page); // 两种判断下一页的方式,选适合你API的: // 方式1:API返回总页数时用总页数判断 const totalPages = Number(data.info.total_pages); const nextPage = currentPage < totalPages ? currentPage + 1 : undefined; // 方式2:API不返回总页数时,用结果数量判断(每页10条,少于10条则无下一页) // const nextPage = data.results.length === 10 ? currentPage + 1 : undefined; return { resultUsers, currentPage, nextPage }; }
第二步:修正useInfiniteQuery的配置
去掉as any断言,让TypeScript做类型检查,同时修正getNextPageParam的取值:
const { isLoading, isError, data, isFetching, refetch } = useInfiniteQuery<FetchUsersResponse>({ queryKey: ['users'], queryFn: fetchUsers, initialPageParam: 1, getNextPageParam: (lastPage) => lastPage.nextPage, // 取正确的nextPage字段 });
第三步:正确观察状态变化
直接在组件顶层console.log会每次渲染都执行,可能看到的是初始状态。用useEffect监听状态变化,才能看到真实的更新:
import { useEffect } from 'react'; useEffect(() => { console.log('当前请求状态:', isFetching); console.log('获取到的数据:', data); }, [isFetching, data]);
第四步:添加错误和加载状态的UI提示
快速排查是否有请求失败的情况:
if (isError) { return <div>数据加载失败,请稍后重试</div>; } if (isLoading) { return <div>加载中...</div>; } // 渲染数据的逻辑 return ( <div> {data?.pages.map((page) => ( <div key={page.currentPage}> {page.resultUsers.map(user => ( <div key={user.id}>{user.firstName} {user.lastName}</div> ))} </div> ))} </div> );
内容的提问来源于stack exchange,提问作者Juan Bautista De Angelis
相关产品推荐
相关产品推荐

