如何在React Query的useInfiniteQuery中统一存储条目总数?
解决useInfiniteQuery中统一存储totalCount的问题
方案1:通过transform重构数据结构
在useInfiniteQuery中使用transform选项,把返回的无限查询数据重新组织成顶层包含统一totalCount的结构,后续更新只需操作这个单一字段:
const { data } = useInfiniteQuery({ queryKey: ['items'], queryFn: async ({ pageParam = 0 }) => { const res = await fetch(`/api/items?page=${pageParam}`); return res.json(); }, getNextPageParam: (lastPage) => lastPage.page + 1, // 转换数据结构,将totalCount提取到顶层 transform: (infiniteData) => { const firstPage = infiniteData.pages[0]; return { totalCount: firstPage?.totalCount || 0, pageParams: infiniteData.pageParams, // 可选:合并所有页的条目,方便直接渲染列表 allItems: infiniteData.pages.flatMap(page => page.items), // 保留原始分页数据,用于分页逻辑 pages: infiniteData.pages }; } });
转换后的数据结构会变成:
{ totalCount: 345, pageParams: [0,1,2], allItems: ["item1", "item2", ...], pages: [...] }
当用户删除条目时,只需更新顶层的totalCount并移除对应条目即可:
queryClient.setQueryData(['items'], (oldData) => { if (!oldData) return oldData; return { ...oldData, totalCount: oldData.totalCount - 1, allItems: oldData.allItems.filter(item => item !== deletedItem), // 可选:如果需要保持各分页的totalCount同步,也可在此修改 pages: oldData.pages.map(page => ({ ...page, totalCount: oldData.totalCount - 1, items: page.items.filter(item => item !== deletedItem) })) }; });
方案2:更新时批量修改所有分页的totalCount
如果不想改动原始数据结构,也可以在更新时遍历所有分页,统一修改totalCount:
queryClient.setQueryData(['items'], (oldData) => { if (!oldData) return oldData; return { ...oldData, pages: oldData.pages.map(page => ({ ...page, totalCount: page.totalCount - 1 })) }; });
这种方式不需要修改查询的转换逻辑,但每次更新都要遍历所有分页,适合数据量不大的场景。
额外提示
- 注意
getNextPageParam的逻辑:如果使用了transform,要确保它基于原始分页数据(即pages数组的最后一项)计算下一页参数,上面的例子中因为保留了pages数组,所以该逻辑可以正常工作。 - 如果删除操作会触发后端数据变更,也可以调用
queryClient.invalidateQueries(['items'])让React Query重新拉取数据,但会产生额外网络请求,适合对实时性要求高且不介意重新请求的场景。
内容的提问来源于stack exchange,提问作者Michal
相关产品推荐
相关产品推荐

