React Query staleTime与动态queryKey使用问题求助
React Query 动态queryKey与staleTime缓存问题解决方案
核心需求实现:缓存已请求过的queryKey数据
要实现「特定queryKey已请求过就直接用缓存、不重复请求」,关键是理清React Query的缓存逻辑和staleTime的作用:
- 设置
staleTime: Infinity:表示对应queryKey的缓存数据永远不会变旧,只要缓存存在,就直接返回缓存值,不会触发后台请求。你之前误以为设置后数据无更新,实际上是切换Producer/Category时,queryKey变成了新的组合(比如["categories", {id: 新ID}]),这是全新的缓存条目,所以会发起新请求;而当再次切回旧ID时,React Query会自动调用对应queryKey的缓存数据,不会重复请求——这正是你需要的行为。 - 无需手动维护缓存,React Query会自动为每个不同的queryKey单独存储缓存条目。
代码优化点
- 移除手动ref缓存逻辑
你用currentCategoriesRef和currentProducersRef维护initialData完全多余,React Query本身会自动管理缓存。直接删除initialData和onSuccess里的ref赋值代码:
const [categories, producers] = useQueries({ queries: [ { queryKey: ["categories", { id: currentProducer }], queryFn: handleFetchCategories, staleTime: Infinity, refetchOnMount: false, refetchOnWindowFocus: false, }, { queryKey: ["producers", { id: currentCategory }], queryFn: handleFetchProducers, staleTime: Infinity, refetchOnMount: false, refetchOnWindowFocus: false, }, ], });
调整refetch触发配置
将refetchOnMount设为false,确保组件挂载时,若对应queryKey已有缓存(且未过期),不会重复发起请求。如果后续需要主动刷新缓存,可通过手动调用方法触发。类型定义优化
避免使用any类型,为接口返回数据定义明确的TypeScript类型,提升代码健壮性:
interface Category { id: number; name: string; // 补充其他业务字段 } const handleFetchCategories = async ({ queryKey }: QueryKey) => { const [_, { id }] = queryKey; const res = await fetch(`/api/producers/${id}/categories`); return res.json() as Promise<Category[]>; };
- 拆分独立useQuery调用
如果两个查询逻辑相对独立,拆分单独的useQuery调用可提升代码可读性:
const categoriesQuery = useQuery({ queryKey: ["categories", { id: currentProducer }], queryFn: handleFetchCategories, staleTime: Infinity, refetchOnMount: false, refetchOnWindowFocus: false, }); const producersQuery = useQuery({ queryKey: ["producers", { id: currentCategory }], queryFn: handleFetchProducers, staleTime: Infinity, refetchOnMount: false, refetchOnWindowFocus: false, });
主动刷新缓存的方法
如果后端数据发生变更,需要主动更新某一queryKey的缓存,可通过queryClient触发:
import { useQueryClient } from '@tanstack/react-query'; const queryClient = useQueryClient(); // 刷新指定Producer的分类缓存 const refreshCategories = (producerId: number) => { queryClient.invalidateQueries({ queryKey: ["categories", { id: producerId }] }); };
调用invalidateQueries后,该queryKey的缓存会被标记为失效,下次使用时会重新请求并更新缓存。
内容的提问来源于stack exchange,提问作者Bartosz Król
相关产品推荐
相关产品推荐

