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

React Query调用queryClient.setQueryData后缓存无法持久化问题

问题:React Query缓存无法持久化及defaultOptions不生效

调用queryClient.setQueryData后缓存无法持久化,配置的defaultOptions未生效。通过React Query开发者工具可见API调用后数据已存储,但发现gcTimeout属性值为23,尝试各类网上方案后仍未解决。目前能通过getQueryData获取到allMappingAreas数据,但约5分钟后会消失。


相关代码配置

1. app.tsx中的QueryClient配置

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: Infinity,
      cacheTime: 100000, // 10分钟
    },
  },
});

<QueryClientProvider client={queryClient}>

2. 自定义mutation钩子useFetch(hooks/useFetch.ts)

const useFetch = (requests: Request[]) => {
  const queryClient = useQueryClient();

  const fetchDataAndMutate = () => {
    return requests.map((request) => {
      const {
        key,
        api, 
        save = true,
      } = request;

      const {mutate, isLoading} = useMutation({
        mutationFn: async (payload) => postUtil(api, payload),
        onMutate: (variables) => {
          return {id: 1};
        },
        onError: (error, variables, context) => {
          console.log(`Error: ${error}`);
        },
        onSuccess: (response, variables, context) => {
          if (response.status) {
            if (response.status === 200) {
              if (save) queryClient.setQueryData([key], response.data.data);
            }
          } else if (response.response.status) {
            console.log(
              "response.response.status",
              response.response.data.Message
            );
          }
        },
      });
      return {
        mutate,
        isLoading,
      };
    });
  };
  const mutates = fetchDataAndMutate();

  useEffect(() => {
    requests.forEach((request, index) => {
      if (request?.init && typeof mutates[index].mutate === "function")
        mutates[index].mutate();
    });
  }, []);

  return mutates;
};

3. 钩子使用方式(containers/analysis)

const apiConfig = [
  {
    key: ALL_MAPPING_AREAS,
    api: getAllMappingAreasApi, 
    init: true,
  },
  {
    key: MAPPING_AREA_DETAIL,
    api: getMappingAreaDetailApi, 
  },
];

const mutates = useFetch(apiConfig);
const [
  getAllMappingAreas,
  getBoundedAreaDetail,
] = mutates;


const allMappingAreas = queryClient.getQueryData([ALL_MAPPING_AREAS]);
const mappingAreaDetail = queryClient.getQueryData([MAPPING_AREA_DETAIL]);

问题根源与解决方案

问题根源

  1. defaultOptions未生效:defaultOptions仅对useQuery创建的查询生效,你用useMutation配合setQueryData手动设置的缓存,不受queries配置项的约束。
  2. 缓存5分钟后消失:React Query的垃圾回收机制会清理无订阅的缓存项,默认等待时间为5分钟(对应gcTimeout)。你仅通过setQueryData添加缓存,但没有组件用useQuery订阅该查询键,所以缓存会被自动回收。

解决步骤

方案1:用useQuery替代mutation初始化数据

对于需要持久化缓存的初始化请求,改用useQuery,这样defaultOptions的配置会生效,且订阅会阻止垃圾回收:

const useFetchQueries = (requests: Request[]) => {
  return requests.map((request) => {
    const { key, api, init = false } = request;
    const query = useQuery({
      queryKey: [key],
      queryFn: () => postUtil(api), // 适配POST请求的查询函数
      enabled: init, // 控制是否自动执行请求
      staleTime: Infinity,
      cacheTime: 100000,
    });
    return {
      refetch: query.refetch,
      isLoading: query.isLoading,
      data: query.data,
    };
  });
};

方案2:手动添加查询订阅(保留mutation场景)

如果必须用mutation设置缓存,需在组件中添加空订阅,阻止垃圾回收:

// 在需要缓存的组件中添加
useQuery({
  queryKey: [ALL_MAPPING_AREAS],
  queryFn: () => Promise.resolve(null),
  enabled: false, // 不自动执行请求
  cacheTime: 100000,
  staleTime: Infinity,
});

方案3:手动更新缓存项配置

通过setQueryData设置缓存后,手动修改缓存项的垃圾回收策略:

queryClient.setQueryData([key], response.data.data);
// 覆盖缓存项的cacheTime配置
queryClient.getQueryCache().get([key])?.setOptions({ cacheTime: 100000 });

内容的提问来源于stack exchange,提问作者sana arshed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 15:17:43