Next.js中使用React Query发起依赖Next-Auth会话令牌的服务端查询
问题原因
你拿不到有效会话数据的核心原因是Hook执行时序和React Query默认行为的匹配问题:
- Next Auth的
useSession在客户端首次挂载时处于加载阶段:此时还未完成会话校验,返回的session值为undefined,直到校验完成、拿到完整会话信息后才会触发组件重渲染,填充真实的userData字段。 - React Query的
useInfiniteQuery默认在组件挂载后立即发起请求,不会等待异步的会话加载完成。第一次执行请求函数时,读到的session?.user?.userData就是undefined,自然拼出了/api?userData=undefined的错误路径。 - 你把查询key写死为固定字符串
'query',后续即使会话加载完成、userData更新为有效值,React Query也感知不到依赖变化,不会自动重新发起正确请求。你在页面中能读到会话值,只是因为会话加载完成后触发了重渲染,错误的请求早在第一次挂载时就已经发出去了。
正确实现方案
只需要做三处核心调整即可解决问题:
- 读取
useSession返回的加载状态,通过React Query的enabled配置项,强制等会话认证完成、userData存在时再发起查询请求。 - 把请求依赖的
userData加入React Query的查询key,保证userData变化时查询会自动重置、用新参数拉取数据。 - 不要在queryFn的参数默认值中引用外部可变变量,避免闭包陷阱缓存旧值导致请求参数错误。
修正后的useApiData.ts代码如下:
// hooks/useApiData.ts async function fetchPage(pageParam: string) { const res = await fetch(pageParam) if (!res.ok) throw new Error('接口请求失败') return res.json() } export default function useApiData() { const { data: session, status } = useSession() const userData = session?.user?.userData return useInfiniteQuery( // 查询key必须带上依赖的动态值,变化时自动触发重查 ['apiDataList', userData], ({ pageParam }) => fetchPage(pageParam), { // 仅在会话认证完成、userData有效值存在时启用查询 enabled: status === 'authenticated' && !!userData, // 初始请求地址,仅在查询启用时生效,此时userData一定有值 initialPageParam: `/api?userData=${userData}`, getNextPageParam: (prevPage) => prevPage.next ?? undefined } ) }
额外注意:你原页面代码中调用的Hook名为useCourseData,和自定义Hook的文件名、导出名useApiData不一致,记得统一命名避免报错。现有页面的isLoading判断逻辑不需要修改,会话加载阶段查询不会启动,isLoading会保持false,等会话就绪开始发请求时会自动变成true,完全兼容现有加载态逻辑。
内容的提问来源于stack exchange,提问作者Dan Luba
相关产品推荐
相关产品推荐

