React Query V5:设置gcTime为Infinity的prefetchQuery未按预期工作
React Query V5 SSR场景下单个查询gcTime设置不生效的问题解决
问题原因
核心原因是JSON不支持序列化Infinity值:
- 你在SSR侧
prefetchQuery和客户端useQuery中设置的gcTime: Infinity,会在dehydrate序列化过程中被转换为null。 - 客户端hydration时,由于全局默认配置
REACT_QUERY_CONFIG中gcTime: 0,React Query会用这个默认值填充脱水后查询的null配置,最终导致单个查询的gcTime被覆盖为0。
注:React Query中单个查询的配置优先级本应高于全局默认,但序列化丢失Infinity是触发该问题的关键。
解决方案
方案1:用超大数值替代Infinity
由于Infinity无法被JSON正常序列化,建议使用足够大的毫秒数模拟“永久保留”缓存,例如设置为10年的毫秒数:
// SSR侧prefetchQuery queryClient.prefetchQuery({ gcTime: 10 * 365 * 24 * 60 * 60 * 1000, // 10年毫秒数 queryKey: PAYWALLS_KEYS.one(config.siteId), queryFn: () => microservicesClient.paywalls.getOne(config.siteId), }) // 客户端自定义hook的useQuery useQuery({ gcTime: 10 * 365 * 24 * 60 * 60 * 1000, queryKey: PAYWALLS_KEYS.one(siteId), queryFn: () => microservicesClient.paywalls.getOne(siteId), });
方案2:客户端hydrate后手动更新查询配置
在客户端应用初始化完成后,通过queryClient.setQueryOptions为目标查询重新设置gcTime,绕过序列化限制:
// 客户端根组件中 import { useEffect } from 'react'; import { useQueryClient } from '@tanstack/react-query'; function AppRoot() { const queryClient = useQueryClient(); const siteId = // 你的siteId取值逻辑 useEffect(() => { queryClient.setQueryOptions({ queryKey: PAYWALLS_KEYS.one(siteId), gcTime: Infinity, }); }, [queryClient, siteId]); return ( {/* 应用其余部分 */} ); }
方案3:调整全局默认配置(可选)
如果多数查询需要保留缓存,仅少数需要gcTime: 0,可以将全局默认gcTime设为超大数值,再为特定查询单独设置gcTime: 0,避免单个查询覆盖时的序列化问题:
const REACT_QUERY_CONFIG = { defaultOptions: { queries: { gcTime: 10 * 365 * 24 * 60 * 60 * 1000, // 全局默认10年 refetchOnMount: false, refetchOnWindowFocus: false, retry: false, staleTime: Infinity, }, mutations: { gcTime: 0, retry: false, }, }, }
验证方法
可以在SSR侧脱水后打印dehydratedState,会发现原本设置的gcTime: Infinity已被转为null,这能直接验证序列化丢失的问题。
内容的提问来源于stack exchange,提问作者Yama94
相关产品推荐
相关产品推荐

