Udemy React 강의 172번 정리
지금까지 App 컴포넌트에서 :
<CartContext.Provider value={...}> 설정즉, Context + State + 로직이 전부 App에 몰려 있음.
이렇게 되면 App 컴포넌트가 점점 거대해지고, Context가 여러 개 생기면 App이 더 복잡해진다.
즉, 루트 컴포넌트는 깔끔해야 한다는 원칙에 어긋남.
Context + State + 관련 로직을 App이 아니라 Context Provider 컴포넌트로 옮기는 것이다.
즉, Context를 사용만 하는 쪽(App)과 Context를 관리하는 쪽(Provider 컴포넌트)를 분리하는 것.
shopping-cart-context의 역할이제 Context 파일은 단순히 createContext만 하는 것이 아니라 (1) 장바구니 state, (2) 아이템 추가 / 수정 로직, (3) Context에 전달할 value 구성, (4) Provider 컴포넌트 렌더링 이 모든 걸 담당한다.
// src/store/shopping-cart-context.jsx
export default function CartContextProvider({ children }) {
const [shoppingCart, setShoppingCart] = useState({
items: [],
});
function handleAddItemToCart(id) {
setShoppingCart(prevShoppingCart => {
const updatedItems = [...prevShoppingCart.items];
const existingCartItemIndex = updatedItems.findIndex(
cartItem => cartItem.id === id
);
const existingCartItem = updatedItems[existingCartItemIndex];
if (existingCartItem) {
const updatedItem = {
...existingCartItem,
quantity: existingCartItem.quantity + 1,
};
updatedItems[existingCartItemIndex] = updatedItem;
} else {
const product = DUMMY_PRODUCTS.find(product => product.id === id);
updatedItems.push({
id: id,
name: product.title,
price: product.price,
quantity: 1,
});
}
return {
items: updatedItems,
};
});
}
function handleUpdateCartItemQuantity(productId, amount) {
setShoppingCart(prevShoppingCart => {
const updatedItems = [...prevShoppingCart.items];
const updatedItemIndex = updatedItems.findIndex(
item => item.id === productId
);
const updatedItem = {
...updatedItems[updatedItemIndex],
};
updatedItem.quantity += amount;
if (updatedItem.quantity <= 0) {
updatedItems.splice(updatedItemIndex, 1);
} else {
updatedItems[updatedItemIndex] = updatedItem;
}
return {
items: updatedItems,
};
});
}
const ctxValue = {
items: shoppingCart.items,
addItemToCart: handleAddItemToCart,
updateItemQuantity: handleUpdateCartItemQuantity,
};
return (
<CartContext.Provider value={ctxValue}>{children}</CartContext.Provider>
);
}
이 컴포넌트는 데이터와 로직을 감싸서 제공하는 역할을 하는 거지, UI를 만들기 위한 게 아님. 그래서 children을 받아서 그대로 감싸줌.