RTK Query轮询停止异常:设置skip后数据变为undefined的问题排查
问题原因
当你把skip设为true时,RTK Query会重置该查询hook的内部状态,包括data字段,所以它会回到初始的undefined值——这是RTK Query的默认行为,目的是在查询被跳过的情况下,不保留过时或不需要的数据。
解决方案
有两种常用方式可以让数据保持为API返回的有效值:
方法1:使用keepUnusedDataFor配置
RTK Query提供了keepUnusedDataFor选项,用于设置数据在查询不再活跃(比如被skip)后保留的时间。你可以把它设为一个足够长的时间,甚至Infinity,这样即使skip为true,之前获取的data也不会被清空。
修改后的代码:
const [skip, setSkip] = useState(false); const { data, error, isError, isLoading, refetch } = useGetReportsQuery({}, { pollingInterval: 15000, skip: skip, keepUnusedDataFor: Infinity // 永久保留数据,也可以设具体秒数,比如3600 }); console.log("DATA:", data); useEffect(() => { if (data != undefined) { console.log("DATA INSIDE USEEFFECT:", data); if(data.some(item => item.status !== "done")) { console.log("polling"); setSkip(false); } else { console.log("stop polling"); setSkip(true); } } }, [data]);
方法2:手动缓存数据
通过额外的useState来保存有效数据,这样即使RTK Query的data被重置,你自己的缓存状态依然保留着之前的有效值。
修改后的代码:
const [skip, setSkip] = useState(false); const [cachedReports, setCachedReports] = useState([]); // 手动缓存数据 const { data, error, isError, isLoading, refetch } = useGetReportsQuery({}, { pollingInterval: 15000, skip: skip }); // 缓存每次获取到的有效数据 useEffect(() => { if (data !== undefined) { setCachedReports(data); } }, [data]); // 业务逻辑使用缓存的数据 useEffect(() => { // 优先用最新的data,没有则用缓存 const currentData = data ?? cachedReports; if (currentData.length > 0) { if(currentData.some(item => item.status !== "done")) { console.log("polling"); setSkip(false); } else { console.log("stop polling"); setSkip(true); } } }, [data, cachedReports]); // 后续展示数据时使用cachedReports console.log("Cached DATA:", cachedReports);
注意事项
- 方法1的优势是无需额外代码,完全利用RTK Query的内置机制;如果之后需要重新开启轮询(
skip设为false),RTK Query会自动发起新请求并更新data。 - 方法2更灵活,你可以完全控制缓存的更新时机和逻辑,适合有特殊缓存需求的场景。
内容的提问来源于stack exchange,提问作者Tibo
相关产品推荐
相关产品推荐

