You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:47:39