TypeScript Redux购物车状态刷新丢失问题求助
购物车状态无法通过redux-persist持久化
我在TypeScript项目中,希望用户点击添加按钮后,购物车状态能持久保留。虽然已经正确注册reducer,也尝试使用redux-persist,但添加商品到购物车后刷新页面,cartReducer的状态仍会丢失。多次参考Redux文档尝试解决都没成功,恳请帮忙排查问题。
相关代码
redux/reducer/cartReducer.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { CartReducerInitialState } from "../../types/reducer-types"; import { CartItem, ShippingInfo } from "../../types/types"; const initialState: CartReducerInitialState = { loading: false, cartItems: [], subtotal: 0, tax: 0, shippingCharges: 0, discount: 0, total: 0, shippingInfo: { address: "", city: "", state: "", country: "", pinCode: "", }, }; export const cartReducer = createSlice({ name: "cartReducer", initialState, reducers: { addToCart: (state, action: PayloadAction<CartItem>) => { state.loading = true; const index = state.cartItems.findIndex( (i) => i.productId === action.payload.productId ); if (index !== -1) state.cartItems[index] = action.payload; else state.cartItems.push(action.payload); state.loading = false; }, removeCartItem: (state, action: PayloadAction<string>) => { state.loading = true; state.cartItems = state.cartItems.filter( (i) => i.productId !== action.payload ); state.loading = false; } }, }); export const { addToCart, removeCartItem } = cartReducer.actions;
redux/store.ts
import { configureStore } from "@reduxjs/toolkit"; import { userAPI } from "./api/userAPI"; import { userReducer } from "./reducer/userReducer"; import { productAPI } from "./api/productAPI"; import { cartReducer } from "./reducer/cartReducer"; import { persistReducer } from 'redux-persist' import storage from 'redux-persist/lib/storage' import {combineReducers} from "@reduxjs/toolkit"; export const server = import.meta.env.VITE_SERVER; const reducers = combineReducers({ [userAPI.reducerPath]: userAPI.reducer, [productAPI.reducerPath]: productAPI.reducer, [userReducer.name]: userReducer.reducer, [cartReducer.name]: cartReducer.reducer }); const persistConfig = { key: 'root', storage, whitelist: ["cartReducer"] }; const persistedReducer = persistReducer(persistConfig, reducers) export const store = configureStore({ reducer: persistedReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat([ userAPI.middleware, productAPI.middleware ]), }); export type RootState = ReturnType<typeof store.getState>
pages/Home.tsx
const { cartItems, subtotal, tax, total, shippingCharges, discount } = useSelector((state: { cartReducer: CartReducerInitialState }) => state.cartReducer) const { data, isError, isLoading } = useLatestProductsQuery("") // console.log(data) console.log(cartItems) const dispatch = useDispatch() const addToCartHandler = (cartItem: CartItem) => { if(cartItem.stock < 1) return toast.error("Out of Stock") dispatch(addToCart(cartItem)) toast.success("Item added to cart") } { data?.products.map((i) => ( <ProductCard key={i._id} productId={i._id} name={i.name} price={i.price} category={i.category} stock={i.stock} handler={addToCartHandler} photo={i.photo} /> )) }
components/ProductCard.tsx
type ProductProps = { productId: string photo: string name: string category: string price: number stock: number handler: (cartItem: CartItem) => string | undefined } const ProductCard = ({ productId, photo, name, category, price, stock, handler }: ProductProps) => { return ( <div className="product-card"> <h3 className="category">{category.toUpperCase()}</h3> <img src={`${server}/${photo}`} alt={name} /> <p>{name}</p> <span>HK$ {price}</span> <div> <button onClick={() => handler({ productId, price, name, category, photo, stock, quantity: 1 })}> <FaPlus /> </button> </div> </div> ) }
types/types.ts
export type CartItem = { productId: string photo: string name: string category: string price: number quantity: number stock: number }
问题排查与解决
你的代码存在两个核心问题,导致redux-persist无法正常工作:
1. 未在根组件包裹PersistGate
redux-persist需要通过PersistGate组件完成持久化状态的加载流程,否则刷新页面后无法从本地存储中恢复状态。
2. 默认中间件未关闭序列化检查
Redux Toolkit的默认中间件会检查状态是否可序列化,而redux-persist的内部状态会触发这个检查,导致状态持久化失败。
具体修复步骤
步骤一:修改redux/store.ts的中间件配置
export const store = configureStore({ reducer: persistedReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false // 关闭序列化检查,避免redux-persist触发警告 }).concat([ userAPI.middleware, productAPI.middleware ]), });
步骤二:在应用根组件添加PersistGate
以main.tsx为例,先导入所需依赖:
import { persistStore } from 'redux-persist'; import { PersistGate } from 'redux-persist/integration/react'; import { store } from './redux/store';
然后创建persistor实例并包裹应用:
const persistor = persistStore(store); ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <App /> {/* 你的应用根组件 */} </PersistGate> </Provider> </React.StrictMode>, );
额外检查
你的CartItem类型均为基础可序列化类型(字符串、数字),无需额外处理。如果后续添加了不可序列化类型(如Date、函数),需要在persistConfig中配置对应的转换规则。
完成以上修改后,刷新页面即可看到购物车状态被正常持久化。
内容的提问来源于stack exchange,提问作者Dominic Sham
相关产品推荐
相关产品推荐

