import { configureStore } from "@reduxjs/toolkit";
import cartReducer from "./cart";
const store = configureStore({
reducer: {
cart: cartReducer,
},
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export default store;
const queryClient = new QueryClient();
const container: HTMLElement = document.getElementById("app")!;
const root = createRoot(container);
root.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<Provider store={store}>
<App />
</Provider>
<ReactQueryDevtools initialIsOpen={true} />
</QueryClientProvider>
</React.StrictMode>
);
1. store에 보관하기 위한 slice(state)와 리듀서 함수 작성
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
const cartSlice = createSlice({
name: "cart",
initialState: loadCartFromLocalStorage(),
reducers: {
addToCart(state, action: PayloadAction<ICartItems>) {
const newItem = action.payload;
const existingItem = state.items.find((item) => item.id === newItem.id);
if (existingItem) {
existingItem.count += newItem.count;
} else {
state.items.push(newItem);
}
state.totalAmount = state.items.reduce((total, item) => total + item.price * item.count, 0);
saveCartToLocalStorage(state);
},
removeFromCart(state, action: PayloadAction<number>) {
const id = action.payload;
const existingItem = state.items.find((item) => item.id === id);
if (existingItem) {
state.totalAmount -= existingItem.price * existingItem.count;
state.items = state.items.filter((item) => item.id !== id);
saveCartToLocalStorage(state);
}
},
},
});
export const { addToCart, removeFromCart, clearCart, increaseItemCount, decreaseItemCount } = cartSlice.actions;
export default cartSlice.reducer;
2. useDispatch()와 useSelector()로 slice와 리듀서 함수 사용하기
import { useDispatch, useSelector } from "react-redux";
const CartList = (): JSX.Element => {
const dispatch: AppDispatch = useDispatch();
const { items, totalAmount } = useSelector((state: RootState) => state.cart);
const handleAddCount = (id: number) => {
dispatch(increaseItemCount(id));
};
3. 장바구니 상태를 localStorage에 저장하고, 로드
const loadCartFromLocalStorage = (): ICartState => {
const savedCart = localStorage.getItem("cartItems");
if (savedCart) {
try {
const { items, totalAmount } = JSON.parse(savedCart);
return {
items: items || [],
totalAmount: totalAmount || 0,
};
} catch (error) {
console.error("Failed to parse cart data from localStorage", error);
return initialState;
}
}
return initialState;
};
const saveCartToLocalStorage = (state: ICartState) => {
const cartData = {
items: state.items,
totalAmount: state.totalAmount,
};
localStorage.setItem("cartItems", JSON.stringify(cartData));
};
문제: console.log(totalAmount)로 디버깅해보니 제대로 업데이트가 안된다고 있음을 발견했다.
원인: 업데이트한 값을 저장하지 않아서 장바구니 totalAmount 초기값은 0을 유지했다.
해결: 업데이트한 값을 localStarage에 저장히고, 저장한 데이터를 불러오는 함수를 만들어 초기값으로 지정했다.
배운 점: 상태를 업데이트한 후엔 localStorage에 저장해 데이터 일관성을 유지해야 한다. 상태 변경 후 저장하지 않으면 페이지를 새로고침했을 때 변경 사항이 반영되지 않을 수 있다.
이외에 Redux를 사용하기 위해 초기에 설정해줘야 할 게 많아 복잡했다. 그래도 store, slice 등을 세팅하고 난 후 상태를 전역에서 사용할 땐 편리했다.
참고: Redux 공식문서