使用RTK Query执行删除查询后数据不刷新的问题
RTK Query删除购物车商品后组件不刷新问题解决
我用RTK Query开发购物车功能,删除商品的接口调用实际有效,但页面不会自动刷新,必须手动刷新才能显示最新购物车状态。试过用useEffect重新挂载组件没用,第一次接触RTK Query,求解决办法。
我的代码
cartSlice.js
import { createSelector, createEntityAdapter } from '@reduxjs/toolkit'; import { apiSlice } from './apiSlice'; const cartAdapter = createEntityAdapter(); const initialState = cartAdapter.getInitialState(); export const cartApiSlice = apiSlice.injectEndpoints({ endpoints: (builder) => ({ getCart: builder.query({ query: () => '/cart', transformResponse: (responseData) => { return cartAdapter.setAll(initialState, responseData); }, providesTags: (result, error, arg) => [ { type: 'Cart', id: 'LIST' }, ...result.ids.map((id) => ({ type: 'Cart', id: 'LIST' })), ], }), addCartItem: builder.mutation({ query: (initialProduct) => ({ url: '/cart', method: 'POST', body: { ...initialProduct, }, }), invalidatesTags: [{ type: 'Cart', id: 'LIST' }], }), deleteCartItem: builder.mutation({ query: (id) => ({ url: `/cart/${id}`, method: 'DELETE', invalidatesTags: (result, error, arg) => [{ type: 'Cart', id: arg.id }], }), }), }), });
Cart组件代码
const CartPage = () => { const dispatch = useDispatch(); const cart = useSelector(selectAllCart); const [deleteCartItem] = useDeleteCartItemMutation( {}, { refetchOnMountOrArgChange: true }, ); const [shippingValue, setShippingValue] = useState(0); const getTotal = () => { let totalQuantity = 0; let totalPrice = 0; cart.forEach((cart) => { totalQuantity += cart.item.quantity; totalPrice += cart.item.price * cart.quantity; }); return { totalPrice, totalQuantity }; }; const handleRemoveFromCart = async (id) => { try { await deleteCartItem(id).unwrap(); } catch (err) { console.error(err); } };
问题原因与解决办法
核心问题是RTK Query的缓存标签(Tags)配置不匹配,导致删除操作后未触发缓存更新和组件刷新。
1. 修正getCart的providesTags配置
原代码中遍历商品ID生成的标签都复用id: 'LIST',导致标签重复且无法精准匹配单个商品,可选两种修正方案:
方案一:仅使用列表级标签(删除后刷新整个购物车)
修改getCart的providesTags:
providesTags: (result, error, arg) => [ { type: 'Cart', id: 'LIST' }, // 只标记整个购物车列表的缓存 ],
方案二:同时提供列表标签和单个商品标签(精准刷新单个商品)
修改为:
providesTags: (result, error, arg) => [ { type: 'Cart', id: 'LIST' }, ...result.ids.map((id) => ({ type: 'Cart', id })), // 每个商品对应独立的标签ID ],
2. 修正deleteCartItem的invalidatesTags配置
根据上面选择的方案,调整删除操作的失效标签:
对应方案一(刷新整个列表)
修改deleteCartItem:
deleteCartItem: builder.mutation({ query: (id) => ({ url: `/cart/${id}`, method: 'DELETE', }), invalidatesTags: [{ type: 'Cart', id: 'LIST' }], // 失效整个列表缓存,触发getCart重新拉取数据 }),
对应方案二(精准失效单个商品)
修改为:
deleteCartItem: builder.mutation({ query: (id) => ({ url: `/cart/${id}`, method: 'DELETE', }), invalidatesTags: (result, error, arg) => [{ type: 'Cart', id: arg }], // arg就是传入的商品ID,直接匹配对应标签 }),
3. 其他小优化
transformResponse中不要直接引用全局的initialState,每次创建新的初始状态避免潜在引用问题:transformResponse: (responseData) => { return cartAdapter.setAll(cartAdapter.getInitialState(), responseData); },- 组件中
useDeleteCartItemMutation无需传空对象作为第一个参数,简化为:const [deleteCartItem] = useDeleteCartItemMutation({ refetchOnMountOrArgChange: true });
原理说明
RTK Query通过providesTags标记缓存数据的身份,invalidatesTags标记哪些操作会使对应缓存失效。当失效标签与提供的标签匹配时,RTK Query会自动重新获取数据,组件就能拿到最新状态并自动刷新。之前的配置中,删除操作的标签与购物车列表的标签不匹配,导致缓存未更新,组件也就不会刷新。
内容的提问来源于stack exchange,提问作者Jacob120
相关产品推荐
相关产品推荐

