Next.js中TanStack React Query未到staleTime仍发起API请求
问题诊断与解决方案
第一步:区分请求来源
先在数据请求函数中添加日志,判断请求是来自服务器还是客户端:
const getSpaceXData = async () => { console.log("请求来源:", typeof window === "undefined" ? "服务器端" : "客户端"); const res = await axios("https://api.spacexdata.com/v4/launches/latest"); return res.data; };
情况1:请求来自服务器端
这说明Next.js在重复执行getStaticProps,常见原因有两种:
开发环境自动刷新
Next.js开发模式下,每次页面请求都会重新运行getStaticProps,属于正常行为。生产环境中静态页面会被缓存,不会频繁触发API请求。生产环境ISR配置不匹配
如果生产环境中getStaticProps设置了revalidate参数且值小于staleTime(比如20秒),会导致Next.js每20秒重新生成页面,进而触发服务器端的API请求。
解决方法:
将revalidate值设置为与staleTime一致(30秒),让ISR重新生成时机与React Query数据过期时机对齐:
export async function getStaticProps() { const queryClient = new QueryClient(); await queryClient.prefetchQuery(["spacex"], getSpaceXData, { staleTime: 30000, }); return { props: { dehydratedState: dehydrate(queryClient), }, revalidate: 30, // 与staleTime保持一致 }; }
情况2:请求来自客户端
说明React Query在客户端主动触发了refetch,可按以下步骤排查:
- 验证Query的staleTime配置
在页面组件中打印当前Query的staleTime,确认是否正确继承了设置的值:
export default function Page() { const { data, query } = useQuery<SpaceXData>(["spacex"], getSpaceXData); console.log("当前Query的staleTime:", query.options.staleTime); // 应输出30000 // ... 其余代码 }
- 关闭不必要的refetch触发条件
修改_app.tsx中的QueryClient配置,关闭可能导致自动refetch的选项:
const queryClient = React.useRef( new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false, retry: false, staleTime: 30000, refetchOnReconnect: false, // 关闭网络重连时的自动refetch refetchOnMount: false, // 可选:强制关闭组件挂载时的refetch(即使数据stale) }, }, }) );
- 检查时间一致性
确保客户端与服务器的系统时间一致,避免因时间差导致React Query误判数据已过期。
额外说明
你代码中使用双QueryClient(服务器端预取一个,客户端hydrate一个)是React Query SSR的标准实践,并非问题根源。
内容的提问来源于stack exchange,提问作者heusenberg batista
相关产品推荐
相关产品推荐

