
(Cart.js)
function Cart() {
const cartItems = useSelector((state) => state.cart);
const dispatch = useDispatch();
const calculateTotal = () => {
return cartItems.reduce((acc, item) => acc + item.price * item.quantity, 0);
};
return (
<div className="cart-container">
{cartItems.map((item) => (
<div className="cart-item">
<input
type="checkbox"
checked={item.selected}
onChange={() => dispatch(toggleSelection(item.id))}
/>
<img src={item.imageUrl} className="product-image" />
<span className="product-name">{item.name}</span>
<span className="product-price">{item.price}원</span>
<div className="quantity-controls">
<button onClick={() => dispatch(decreaseQuantity(item.id))}>
-
</button>
<input
type="number"
value={item.quantity}
readOnly
className="product-quantity"
/>
<button onClick={() => dispatch(increaseQuantity(item.id))}>
+
</button>
</div>
<button onClick={() => dispatch(removeItem(item.id))}>삭제</button>
</div>
))}
<div className="cart-actions">
<button onClick={() => dispatch(removeSelectedItems())}>
선택 삭제
</button>
<button onClick={() => dispatch(removeAllItems())}>전체 삭제</button>
<button>선택 상품 주문</button>
<button>전체 상품 주문</button>
</div>
<div className="cart-summary">
<div>주문 금액: {calculateTotal()}원</div>
<div>배송비: 3000원</div>
<div>합계: {calculateTotal() + 3000}원</div>
</div>
<button className="checkout">주문하기</button>
</div>
);
}
(store.js)
const cart = createSlice({
name: "cart",
initialState: [
{
id: 1,
name: "보송보송타월",
price: 7900,
quantity: 1,
selected: false,
imageUrl:
"https://raw.githubusercontent.com/mimkong/meongmeongdata/master/item1.jpg",
},
{
id: 2,
name: "선데이백",
price: 169000,
quantity: 2,
selected: false,
imageUrl:
"https://raw.githubusercontent.com/mimkong/meongmeongdata/master/item2.jpg",
},
],
reducers: {
toggleSelection: (state, action) => {
const item = state.find((item) => item.id === action.payload);
if (item) item.selected = !item.selected;
},
increaseQuantity: (state, action) => {
const item = state.find((item) => item.id === action.payload);
if (item) item.quantity += 1;
},
decreaseQuantity: (state, action) => {
const item = state.find((item) => item.id === action.payload);
if (item && item.quantity > 1) item.quantity -= 1;
},
removeItem: (state, action) => {
return state.filter((item) => item.id !== action.payload);
},
removeSelectedItems: (state) => {
return state.filter((item) => !item.selected);
},
removeAllItems: () => {
return [];
},
},
});
export default configureStore({
reducer: {cart: cart.reducer },
});
export const {
toggleSelection,
increaseQuantity,
decreaseQuantity,
removeItem,
removeSelectedItems,
removeAllItems,
} = cart.actions;
(redux 쓰기 전)
function Cart() {
const [cartItems, setCartItems] = useState([
{
id: 1,
name: "보송보송타월",
price: 4900,
quantity: 1,
selected: false,
imageUrl: "path_to_imageA.jpg",
},
{
id: 2,
name: "Product B",
price: 20,
quantity: 2,
selected: false,
imageUrl: "path_to_imageB.jpg",
},
]);
const toggleSelection = (id) => {
const updatedCart = cartItems.map((item) =>
item.id === id ? { ...item, selected: !item.selected } : item
);
setCartItems(updatedCart);
};
const increaseQuantity = (id) => {
const updatedCart = cartItems.map((item) =>
item.id === id ? { ...item, quantity: item.quantity + 1 } : item
);
setCartItems(updatedCart);
};
const decreaseQuantity = (id) => {
const updatedCart = cartItems.map((item) =>
item.id === id && item.quantity > 1
? { ...item, quantity: item.quantity - 1 }
: item
);
setCartItems(updatedCart);
};
const removeSelectedItems = () => {
const updatedCart = cartItems.filter((item) => !item.selected);
setCartItems(updatedCart);
};
const removeAllItems = () => {
setCartItems([]);
};
const calculateTotal = () => {
return cartItems.reduce((acc, item) => acc + item.price * item.quantity, 0);
};
return (
<div className="cart-container">
{cartItems.map((item) => (
<div className="cart-item" key={item.id}>
<input
type="checkbox"
checked={item.selected}
onChange={() => toggleSelection(item.id)}
/>
<img src={item.imageUrl} className="product-image" />
<span className="product-name">{item.name}</span>
<span className="product-price">{item.price}원</span>
<div className="quantity-controls">
<button onClick={() => decreaseQuantity(item.id)}>-</button>
<input
type="number"
value={item.quantity}
readOnly
className="product-quantity"
/>
<button onClick={() => increaseQuantity(item.id)}>+</button>
</div>
<button
onClick={() =>
setCartItems(cartItems.filter((ci) => ci.id !== item.id))
}
>
삭제
</button>
</div>
))}
<div className="cart-actions">
<button onClick={removeSelectedItems}>선택 삭제</button>
<button onClick={removeAllItems}>전체 삭제</button>
<button>선택 상품 주문</button>
<button>전체 상품 주문</button>
</div>
<div className="cart-summary">
<div>주문 금액: {calculateTotal()}원</div>
<div>배송비: 3000원</div>
<div>합계: {calculateTotal() + 3000}원</div>
</div>
<button className="checkout">주문하기</button>
</div>
);
}
- 처음부터 store.js에 저장하는 것은 아직 익숙하지가 않아 useState를 사용해서 틀을 먼저 잡았다.
toggleSelection: (state, action) => {
const item = state.find((item) => item.id === action.payload);
if (item) item.selected = !item.selected;
},
increaseQuantity: (state, action) => {
const item = state.find((item) => item.id === action.payload);
if (item) item.quantity += 1;
},
decreaseQuantity: (state, action) => {
const item = state.find((item) => item.id === action.payload);
if (item && item.quantity > 1) item.quantity -= 1;
}
if(item)
은 item이 undefined인지 아닌지 확인한다.
만약 if문이 없다면 item이 undefined인 경우 item.selected에 접근할 때 "Cannot read properties of undefined" 라는 오류가 발생한다.