如何用react-query 4处理队列:逐个处理并移除已处理数据
React Query 4 本地缓存移除已处理队列项方案
核心思路
直接通过 React Query 的 queryClient.setQueryData 方法修改对应查询键的缓存数据,将已处理项从缓存数组中移除。组件无需额外维护索引,直接从 useQuery 返回的缓存数据中取第一项展示即可。
具体实现步骤
1. 获取 QueryClient 实例
在需要操作缓存的组件或自定义 Hook 中,通过 useQueryClient 钩子拿到 QueryClient 对象,用于后续操作缓存。
2. 编写处理队列项的 Mutation
在用户完成左滑/右滑操作后,触发修改服务器数据的 Mutation,并在回调中同步更新本地缓存,移除已处理的队列项。
3. 调整组件展示逻辑
不再依赖 useContext 维护索引,直接从 useQuery 返回的 data 中取第一个元素作为当前展示项——缓存数组每次处理后都会移除首项,新的首项自然就是下一个待处理内容。
代码示例
import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query'; // 模拟处理队列项的服务器请求 const processQueueItem = async (queueItem: QueueObject) => { return fetchAuth(`/queue/${queueItem.id}/process`, { method: 'POST', body: JSON.stringify({ status: 'processed' }) }); }; function QueueDisplayComponent({ queueType }: { queueType: QueueType }) { const queryClient = useQueryClient(); const queryKey = ['getQueue', queueType]; // 获取队列缓存数据 const { data: queueData } = useMyQueue(queueType); // 处理队列项的 Mutation const processMutation = useMutation({ mutationFn: processQueueItem, onSuccess: () => { // 更新缓存:移除第一个已处理项 queryClient.setQueryData<QueryReturnQueue>(queryKey, (oldData) => { if (!oldData || !Array.isArray(oldData)) return oldData; // 复制原数组并移除首项,避免直接修改缓存原数据 const newQueue = [...oldData]; newQueue.shift(); // 数组为空时返回 false,匹配你的类型定义 return newQueue.length > 0 ? newQueue : false; }); }, // 可选:启用乐观更新,用户操作后立即更新缓存,失败时回滚 // onMutate: async (queueItem) => { // await queryClient.cancelQueries({ queryKey }); // const oldData = queryClient.getQueryData<QueryReturnQueue>(queryKey); // // 立即更新缓存 // queryClient.setQueryData<QueryReturnQueue>(queryKey, (old) => { // if (!old || !Array.isArray(old)) return old; // const newQueue = [...old]; // newQueue.shift(); // return newQueue.length > 0 ? newQueue : false; // }); // return { oldData }; // }, // onError: (_err, _variables, context) => { // if (context?.oldData) { // queryClient.setQueryData(queryKey, context.oldData); // } // } }); // 当前待展示的队列项 const currentItem = Array.isArray(queueData) ? queueData[0] : null; const handleProcess = () => { currentItem && processMutation.mutate(currentItem); }; if (!currentItem) { return <div>队列已空</div>; } return ( <div className="queue-item"> <h3>{currentItem.title}</h3> <button onClick={handleProcess}>处理当前项</button> </div> ); }
关键说明
setQueryData接收一个函数,参数为旧缓存数据,返回新缓存数据,避免直接修改原缓存引发的问题。- 针对你的
QueryReturnQueue类型(数组或 false),添加了类型判断,确保操作安全。 - 乐观更新为可选配置:如果希望用户操作后立即看到队列推进效果,可启用该逻辑,服务器请求失败时自动回滚缓存。
内容的提问来源于stack exchange,提问作者Patrick Kenny
相关产品推荐
相关产品推荐

