如何使用React Query在单次请求中获取多个ID对应的数据?
批量ID查询的React Query最优实现方案
针对单次GET请求获取多ID数据的场景,结合React Query的原生缓存能力,推荐以下两种递进式的最优实践:
1. 基础方案:批量查询+自动同步单ID缓存
核心思路是将批量请求作为独立查询,同时在请求成功后自动把每个返回项存入对应单ID的缓存键中——既保证批量请求的高效性,又能让后续单个ID查询直接复用缓存。
import { useQuery, QueryClient } from '@tanstack/react-query'; // 假设API请求函数:传入ID数组,返回对应对象数组 const fetchItemsByIds = async (ids: string[]) => { const res = await fetch(`/api/items?ids=${ids.join(',')}`); return res.json(); }; export const useFetchItemsByIds = (ids: string[]) => { const queryClient = useQueryClient(); // 排序ID数组,确保相同ID集合不管顺序都命中同一缓存 const sortedIds = [...ids].sort(); return useQuery({ queryKey: ['items', sortedIds], queryFn: () => fetchItemsByIds(sortedIds), onSuccess: (items) => { // 请求成功后,将每个item单独存入单ID缓存 items.forEach(item => { queryClient.setQueryData(['item', item.id], item); }); }, // 空数组时不发起请求 enabled: sortedIds.length > 0, }); };
方案优势
- 批量请求的缓存会根据ID集合自动管理,重复相同ID集合的查询直接读缓存
- 后续如果有组件用
useQuery(['item', 'xxx'])查询单个数据,能直接命中缓存,无需额外请求
2. 进阶方案:按需请求(减少冗余网络请求)
如果想进一步优化,可以先筛选出缓存中不存在的ID,仅对缺失的ID发起请求,再合并缓存数据和新请求数据返回。
export const useFetchItemsByIds = (ids: string[]) => { const queryClient = useQueryClient(); const sortedIds = [...ids].sort(); // 从缓存中提取已存在的items const cachedItems = sortedIds .map(id => queryClient.getQueryData(['item', id])) .filter(Boolean); // 获取未缓存的ID const cachedIds = new Set(cachedItems.map(item => item.id)); const missingIds = sortedIds.filter(id => !cachedIds.has(id)); return useQuery({ queryKey: ['items', sortedIds], queryFn: () => fetchItemsByIds(missingIds), // 用缓存数据作为初始值,实现即时渲染 initialData: () => cachedItems, onSuccess: (newItems) => { // 更新新获取的item到单ID缓存 newItems.forEach(item => { queryClient.setQueryData(['item', item.id], item); }); // 更新批量查询的缓存为合并后的数据 queryClient.setQueryData(['items', sortedIds], [...cachedItems, ...newItems]); }, // 只有存在缺失ID时才发起请求 enabled: missingIds.length > 0, // 即使没有发起请求,也返回完整的合并数据 select: (data) => { if (!data) return cachedItems; return [...cachedItems, ...data]; }, }); };
方案优势
- 完全避免对已缓存ID的重复请求,极大减少网络开销
- 组件能立即拿到已缓存的数据渲染,请求完成后自动补充新数据,体验更流畅
注意事项
- 务必对ID数组排序后作为查询键的一部分,避免因ID顺序不同导致重复缓存
- 如果后端返回的数组顺序和请求ID顺序不一致,需要在
select或onSuccess中按原ID顺序重新整理数据,保证返回结果的顺序正确性
内容的提问来源于stack exchange,提问作者cocoas
相关产品推荐
相关产品推荐

