리액트로 온라인 마켓에서의 장바구니에 추가, 물품 삭제, 수량 조절하는 과제를 페어와 함께 진행했다. 수량을 조절하는 부분이 어려워서 고민을 했었기에 수량조절 부분을 기록해보려고 한다.
function App() {
const [items, setItems] = useState(initialState.items);
const [cartItems, setCartItems] = useState(initialState.cartItems);
//이 부분이 수량 조절 하는 부분 함수다.
const handleQuantity = (quantity, itemId) => {
const newCartItems = [...cartItems]
let findIdx = cartItems.findIndex((item) => item.itemId === itemId)
newCartItems[findIdx].quantity = quantity
setCartItems([...newCartItems])
}
//props로 handleQuantity를 <ShoppingCart/>에 보내주고 있다.
return (
<Router>
<Nav counter={cartItems}/>
<Switch>
<Route exact={true} path="/">
<ItemListContainer
items={items}
addCart={addCart} />
</Route>
<Route path="/shoppingcart">
<ShoppingCart cartItems={cartItems}
items={items}
removeCart={removeCart}
handleQuantity={handleQuantity}/>
</Route>
</Switch>
</Router>
);
}
export default function ShoppingCart({ items, cartItems, removeCart,handleQuantity }) {
const [checkedItems, setCheckedItems] = useState(cartItems.map((el) => el.itemId))
//handleQuantity에 인자로 quantity, itemId를 넘겨주고 있다.
const handleQuantityChange = (quantity, itemId) => {
handleQuantity(quantity, itemId)
}
return (
<div id="item-list-container">
<div id="item-list-body">
<div id="item-list-title">장바구니</div>
<span id="shopping-cart-select-all">
<input
type="checkbox"
checked={
checkedItems.length === cartItems.length ? true : false
}
onChange={(e) => handleAllCheck(e.target.checked)} >
</input>
<label >전체선택</label>
</span>
<div id="shopping-cart-container">
{!cartItems.length ? (
<div id="item-list-text">
장바구니에 아이템이 없습니다.
</div>
) : (
<div id="cart-item-list">
{renderItems.map((item, idx) => {
const quantity = cartItems.filter(el => el.itemId === item.id)[0].quantity
return <CartItem
key={idx}
handleCheckChange={handleCheckChange}
handleQuantityChange={handleQuantityChange}
handleDelete={handleDelete}
item={item}
checkedItems={checkedItems}
quantity={quantity}
/>
})}
</div>
)}
<OrderSummary total={total.price} totalQty={total.quantity} />
</div>
</div >
</div>
)
}
export default function CartItem({
item,
checkedItems,
handleCheckChange,
handleQuantityChange,
handleDelete,
quantity
}) {
return (
<li className="cart-item-body">
<input
type="checkbox"
className="cart-item-checkbox"
onChange={(e) => {
handleCheckChange(e.target.checked, item.id)
}}
checked={checkedItems.includes(item.id) ? true : false} >
</input>
<div className="cart-item-thumbnail">
<img src={item.img} alt={item.name} />
</div>
<div className="cart-item-info">
<div className="cart-item-title" data-testid={item.name}>{item.name}</div>
<div className="cart-item-price">{item.price} 원</div>
</div>
<input
type="number"
min={1}
className="cart-item-quantity"
value={quantity}
onChange={(e) => {
handleQuantityChange(Number(e.target.value), item.id)
}}>
</input>
<button className="cart-item-delete" onClick={() => { handleDelete(item.id) }}>삭제</button>
</li >
)
}
스프린트를 풀면서 React의 '상태'에 좀 더 익숙해 질 수 있어서 좋았다. 내일은 Redux를 사용하여 오늘과 같은 웹페이지를 구현하게 될텐데 Redux가 상태관리를 따로 바깥에서 할 수 있다는것으로 알고 있다. Redux를 사용하면 동일한 페이지를 또 어떤 방식으로 구현할 수 있는지 기대된다.