如何让react-query的select在单个item缓存更新时重新执行?
解决TanStack Query列表查询不跟随单个条目缓存更新的问题
你的问题核心在于:['items']查询的缓存是单纯的ID数组,只要这个数组本身没变化,TanStack Query就不会重新执行select逻辑。单个条目['items', id]的缓存更新不会影响ID数组,所以select不会触发。要避免重复存储数据,同时让列表能感知单个条目变化,可以用以下两种方案:
方案一:在单个条目更新时触发列表查询的重新计算
在更新单个条目的mutation的onSuccess回调里,手动更新['items']查询的缓存(只需改变数组引用,内容不变),这样TanStack Query会认为列表数据有更新,自动重新执行select,从而获取最新的单个条目数据,且不需要重新发起列表请求。
示例代码:
// 单个条目更新的mutation const updateItemMutation = useMutation({ mutationFn: async (updatedItem) => { const res = await fetch(`/items/${updatedItem.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updatedItem), }); return res.json(); }, onSuccess: (updatedItem) => { // 更新单个条目缓存 queryClient.setQueryData(['items', updatedItem.id], updatedItem); // 触发列表查询重新执行select:创建新数组保持内容一致但改变引用 queryClient.setQueryData(['items'], (oldIds) => [...oldIds]); }, });
你的原useItems查询不需要修改,这样当单个条目更新后,列表会自动重新通过select从缓存取最新数据。
方案二:使用useQueries并行获取单个条目
放弃select逻辑,改用useQueries直接并行查询每个单个条目,利用TanStack Query的缓存机制自动复用已有数据。这种方式会自动监听单个条目缓存的变化,一旦更新就会同步到列表中。
示例代码:
export const useItems = () => { const queryClient = useQueryClient(); // 先获取ID列表并初始化单个条目缓存 const { data: ids, isLoading: idsLoading } = useQuery({ queryKey: ['items'], queryFn: async () => { const items = await fetch(); items.forEach((i) => queryClient.setQueryData(['items', i.id], i)); return items.map((i) => i.id); }, }); // 并行查询每个单个条目(优先用缓存,无缓存时才请求) const itemQueries = useQueries({ queries: ids?.map(id => ({ queryKey: ['items', id], queryFn: async () => { const cachedItem = queryClient.getQueryData(['items', id]); if (cachedItem) return cachedItem; // 缓存不存在时才发起单个条目请求 const res = await fetch(`/items/${id}`); return res.json(); }, })) || [], }); // 整理最终的条目数据,处理加载/错误状态 const items = itemQueries .filter(query => query.isSuccess) .map(query => query.data); const isLoading = idsLoading || itemQueries.some(query => query.isLoading); const isError = itemQueries.some(query => query.isError); return { items, isLoading, isError }; };
这种方式无需手动触发更新,单个条目缓存变化后会自动同步到列表,但需要管理多个查询的状态,适合条目数量不多的场景。
内容的提问来源于stack exchange,提问作者JonnySmalls
相关产品推荐
相关产品推荐

