如何在RTK Query中获取历史数据以实现删除项通知?
更贴合RTK的实现方案
方案1:使用RTK Query的onCacheEntryAdded生命周期钩子
这个钩子允许你直接介入缓存的创建与更新流程,方便对比新旧数据:
- 在调用
useGetSomeDataQuery时传入queryOptions,配置onCacheEntryAdded - 通过
cacheDataLoaded获取初始缓存数据,再通过updateCachedData监听后续的缓存更新 - 每次缓存更新时,对比新旧数据找出被移除的ID,触发通知逻辑
const { data, isLoading } = useGetSomeDataQuery(undefined, { onCacheEntryAdded: async (args, { cacheDataLoaded, cacheEntryRemoved, updateCachedData }) => { let currentData = await cacheDataLoaded; const unsubscribe = updateCachedData((newData) => { // 筛选出被移除的ID const removedIds = currentData.filter(item => !newData.some(newItem => newItem.id === item.id)).map(item => item.id); removedIds.forEach(id => { // 替换成你的通知逻辑,比如调用全局通知函数 console.log(`ID为${id}的项已处理并从队列中移除`); }); // 更新当前数据为最新值,供下次对比使用 currentData = newData; return newData; }); await cacheEntryRemoved; unsubscribe(); } });
方案2:自定义RTK中间件全局处理
如果多个组件都需要这类逻辑,自定义中间件可以实现全局监听:
- 监听RTK Query的
fulfilled类型action,筛选目标接口的更新事件 - 获取旧缓存数据和新返回数据,对比差异后触发通知
const cacheDiffMiddleware = store => next => action => { // 匹配目标接口的成功action if (action.type.endsWith('/fulfilled') && action.meta.arg.endpointName === 'getSomeData') { const state = store.getState(); const oldData = state.api.queries.getSomeData?.data; const newData = action.payload; if (oldData && newData) { const removedIds = oldData.filter(item => !newData.some(newItem => newItem.id === item.id)).map(item => item.id); removedIds.forEach(id => { // 这里可以dispatch一个显示通知的action,或者调用通知工具 store.dispatch(showNotification(`ID为${id}的项已处理并从队列中移除`)); }); } } return next(action); }; // 在configureStore时添加该中间件 const store = configureStore({ reducer: { api: api.reducer, // 其他reducer }, middleware: getDefaultMiddleware => getDefaultMiddleware().concat(api.middleware, cacheDiffMiddleware), });
方案3:使用useQuerySubscription订阅缓存更新
useQuerySubscription是专门用于订阅查询缓存变化的钩子,适配轮询这类持续更新场景:
- 订阅目标接口的缓存更新,每次有新数据时触发
onCacheUpdated回调 - 在回调中直接获取
oldData和newData,对比后处理通知
import { useQuerySubscription } from '@reduxjs/toolkit/query/react'; import { api } from './yourApiSlice'; const QueueComponent = () => { const { data, isLoading } = useGetSomeDataQuery(); useQuerySubscription(api.endpoints.getSomeData, { onCacheUpdated: (args, { oldData, newData }) => { if (!oldData || !newData) return; const removedIds = oldData.filter(item => !newData.some(newItem => newItem.id === item.id)).map(item => item.id); removedIds.forEach(id => { // 执行你的通知逻辑 alert(`ID为${id}的项已处理并从队列中移除`); }); } }); // 组件渲染代码 };
以上方案都无需额外使用useState存储本地状态,完全基于RTK生态的缓存机制实现,更符合RTK的设计理念,也能避免本地状态与缓存不同步的问题。
内容的提问来源于stack exchange,提问作者Sergei Basharov
相关产品推荐
相关产品推荐

