RTK Query:upsertQueryData缓存后useGetInstrumentQuery仍发起重复请求
解决RTK Query中
useGetInstrumentQuery重复请求的问题 1. 确保缓存Key完全匹配
检查getBulkInstrument中upsertQueryData使用的refId,和调用useGetInstrumentQuery时传入的refId类型、值完全一致:
- 比如接口返回的refId是数字类型,而组件调用时传的是字符串,会导致缓存Key不匹配,触发新请求。
- 可以在代码中添加日志验证:
同时在组件中打印调用参数:instrumentList.forEach((inst) => { const targetRefId = inst.instrument.refId; console.log('Upserting refId:', typeof targetRefId, targetRefId); dispatch( ApiSlice.util.upsertQueryData('getInstrument', targetRefId, inst.instrument) ); });const refId = 'xxx'; // 或从props获取 console.log('Using refId:', typeof refId, refId); const { data } = useGetInstrumentQuery(refId);
2. 调整缓存有效期
当前keepUnusedDataFor: 1(1秒)过短,缓存会被快速回收,后续调用时缓存已失效,导致重新请求。根据业务需求调整为合理时长:
export const marketApi = ApiSlice.injectEndpoints({ tagTypes: ['Market'], keepUnusedDataFor: 60, // 改为60秒,可根据实际情况调整 endpoints: (builder) => ({ // ... 端点配置 }), });
3. 保证缓存数据结构一致
upsertQueryData存入的数据结构必须和getInstrument接口返回的结构完全一致:
- 如果
getInstrument返回的是单个instrument对象,而getBulkInstrument返回的inst包含instrument嵌套字段,需调整upsert的数据源:instrumentList.forEach((inst) => { // 确保存入缓存的数据和getInstrument返回结构一致 const instrumentData = inst.instrument; dispatch( ApiSlice.util.upsertQueryData('getInstrument', instrumentData.refId, instrumentData) ); }); - 如果
getInstrument配置了transformResponse,需对批量获取的数据执行相同的转换逻辑后再存入缓存。
4. 检查组件调用参数
确保组件中调用useGetInstrumentQuery时,未设置强制刷新的选项:
- 避免使用
refetchOnMountOrArgChange: true、refetchOnFocus: true等会触发自动刷新的配置(除非业务需要):// 错误示例:强制刷新 const { data } = useGetInstrumentQuery(refId, { refetchOnMountOrArgChange: true }); // 正确示例:优先使用缓存 const { data } = useGetInstrumentQuery(refId);
5. 完善缓存写入的安全性
在getBulkInstrument的onCacheEntryAdded中,添加数据存在性校验,避免写入空数据:
async onCacheEntryAdded( arg, { cacheDataLoaded, cacheEntryRemoved, dispatch, getCacheEntry } ) { await cacheDataLoaded; const { refIds } = arg; const instrumentList = getCacheEntry().data; // 校验数据有效性 if (!instrumentList || !Array.isArray(instrumentList)) { await cacheEntryRemoved; return; } // subscribe socket refIds.forEach((refId) => { dispatch(ApiSlice.endpoints.subscribeSocket.initiate(`instruments.${refId}`)); }); instrumentList.forEach((inst) => { dispatch( ApiSlice.util.upsertQueryData('getInstrument', inst.instrument.refId, inst.instrument) ); }); await cacheEntryRemoved; }
内容的提问来源于stack exchange,提问作者Amir Rezvani
相关产品推荐
相关产品推荐

