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

如何为同一RTK Query端点的不同查询参数设置动态缓存有效期?

同一RTK Query端点按请求参数配置不同缓存有效期的方案

RTK Query本身不支持直接为同一端点的不同查询参数设置差异化的keepUnusedDataFor,但可以通过以下几种方案实现类似需求:

方案1:拆分端点(最简洁)

如果不同参数对应的数据集缓存需求差异明确,可以直接将原端点拆分为多个独立端点,每个端点单独配置keepUnusedDataFor。

示例代码:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const dataApi = createApi({
  reducerPath: 'dataApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (builder) => ({
    // 短缓存数据集端点
    getShortLivedDataset: builder.query({
      query: (params) => `/data?type=${params.type}`,
      keepUnusedDataFor: 60, // 缓存1分钟
    }),
    // 长缓存数据集端点
    getLongLivedDataset: builder.query({
      query: (params) => `/data?type=${params.type}`,
      keepUnusedDataFor: 3600, // 缓存1小时
    }),
  }),
});

export const { useGetShortLivedDatasetQuery, useGetLongLivedDatasetQuery } = dataApi;

方案2:手动修改缓存条目过期时间

利用RTK Query的transformResponse钩子,结合updateQueryData工具,在请求完成后根据参数动态修改对应缓存条目的过期时间。

示例代码:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const dataApi = createApi({
  reducerPath: 'dataApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (builder) => ({
    getDataset: builder.query({
      query: (params) => `/data?type=${params.type}`,
      keepUnusedDataFor: 0, // 先设为0,后续手动覆盖
      transformResponse: (response, meta, arg) => {
        // 根据参数判断缓存时长(示例:temp类型缓存1分钟,其他缓存1小时)
        const cacheDuration = arg.type === 'temp' ? 60 : 3600;
        const expiresTime = Date.now() + cacheDuration * 1000;
        
        // 更新当前缓存条目的过期时间
        meta.dispatch(dataApi.util.updateQueryData('getDataset', arg, (draft) => {
          draft.expiresTime = expiresTime;
        }));
        
        return response;
      },
    }),
  }),
});

export const { useGetDatasetQuery } = dataApi;

方案3:自定义缓存逻辑(最高自由度)

通过skipCache: true关闭RTK Query的默认缓存,自行在Redux Slice或组件中实现缓存管理,包括数据存储、过期时间设置和自动清理逻辑。

示例代码:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { createSlice } from '@reduxjs/toolkit';
import { useSelector, useDispatch } from 'react-redux';
import { useEffect } from 'react';

// 自定义缓存Slice
const cacheSlice = createSlice({
  name: 'dataCache',
  initialState: {},
  reducers: {
    setCache: (state, action) => {
      const { key, data, expiresIn } = action.payload;
      state[key] = {
        data,
        expiresAt: Date.now() + expiresIn * 1000,
      };
    },
    clearExpiredCache: (state) => {
      const now = Date.now();
      Object.keys(state).forEach(key => {
        if (state[key].expiresAt < now) delete state[key];
      });
    },
  },
});

export const { setCache, clearExpiredCache } = cacheSlice.actions;
export const dataCacheReducer = cacheSlice.reducer;

// 定义API,跳过RTK Query默认缓存
export const dataApi = createApi({
  reducerPath: 'dataApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (builder) => ({
    getDataset: builder.query({
      query: (params) => `/data?type=${params.type}`,
      skipCache: true,
    }),
  }),
});

// 组件中使用自定义缓存
function DataComponent({ type }) {
  const cacheKey = `dataset_${type}`;
  const cachedData = useSelector(state => state.dataCache[cacheKey]);
  const { data, error, isLoading } = dataApi.useGetDatasetQuery({ type });
  const dispatch = useDispatch();

  useEffect(() => {
    if (data) {
      const expiresIn = type === 'temp' ? 60 : 3600;
      dispatch(setCache({ key: cacheKey, data, expiresIn }));
    }
    // 每分钟清理一次过期缓存
    const interval = setInterval(() => dispatch(clearExpiredCache()), 60000);
    return () => clearInterval(interval);
  }, [data, type, dispatch]);

  // 优先使用未过期的缓存数据
  const displayData = cachedData?.expiresAt > Date.now() ? cachedData.data : data;

  if (isLoading) return <div>加载中...</div>;
  if (error) return <div>加载失败</div>;
  return <div>{JSON.stringify(displayData)}</div>;
}

方案选择建议

  • 若参数对应的缓存规则分组清晰,优先选择拆分端点,实现成本最低且易维护;
  • 若不想拆分端点,可使用手动修改过期时间的方案,在原有端点基础上扩展;
  • 若需要完全自定义缓存策略(如LRU淘汰、多维度过期规则),则选择自定义缓存逻辑。

内容的提问来源于stack exchange,提问作者Indranil Mondal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:36:22