본문 바로가기

공부기록/[강의노트] Udemy React 완벽가이드 101~200

# 152 [udemy React 완벽 가이드 노트] 장바구니에 물건 추가해보기

장바구니 항목을 추가하려면 장바구니 데이터를 관리하는

CartProvider.js에서 작성해야 한다.

 

 

목표 


addItemToCartHandler가 호출될 때마다 

장바구니에 추가 할 item을 얻는다. 

 

이미 item이 이미 장바구니에 들어있는지 보고 

있다면 기존항목을 업데이트하고 

없다면 새로 항목을 추가하고자 한다.

 

그러려면 CartProvider의 컴포넌트를 state로 관리하여야 한다. 

컴포넌트 즉, context, context의 영향을 받는 컴포넌트를 

장바구니 데이터가 변경될 때마다 재평가 되도록 말이다. 

 

 

useState 또는 useReducer를 사용하자

여기서는  useReducer를 사용. (state가 복잡하기 때문)


1) useReducer를 import한다. 

 

 

2) CartProvider 컴포넌트 밖에서 cartReducer 함수를 작성한다. 

 

const cartReducer = (state, action) => {
  if (action.type === "ADD") {
    const updatedItems = state.items.concat(action.item);
    const updatedTotalAmount =
      state.totalAmount + action.item.price * action.item.amount;
    return {
      items: updatedItems,
      totalAmount: updatedTotalAmount,
    };
  }
  if (action.type === "REMOVE") {
  }
  return defaultCartState;
};

 

 

 3) defaultCartState를 작성하고 cadrtReducer에 이것을 return 한다.

리듀서 함수에서 새 state 스냅샷을 반환해야 하기 때문에 작성하는 것.

 

const defaultCartState = {
  items: [],
  totalAmount: 0,
};

 

 

4) CartProvider에서 useReducer를 작성한다.

 

const CartProvier = props => {
  const [cartState, dispatchCartAction] = useReducer(
    cartReducer,
    defaultCartState
  );

 

 

cartState는 항상 최신 스냅샷객체이기 때문에 

cartContext에서 필요하다. 

 

 

5) cartState를 넣어 cartContext에 다음과 같이 수정한다. 

 const cartContext = {
    items: cartState.items,
    totalAmount: cartState.totalAmount,
    addItem: addItemToCartHandler,
    removeItem: removeItemFromCartHandler,
  };

 

 item은 cartState.items로 관리하고 있고 

totalAmount는 cartState.totalAmount로 관리하고 있기 때문이다. 

 

6) 다음과 같이 함수에 dispatchCartAction을 추가해준다. 

 

const addItemToCartHandler = item => {
    dispatchCartAction({ type: "ADD", item: item });
  };

  const removeItemFromCartHandler = id => {
    dispatchCartAction({ type: "REMOVE", id: id });
  };

이렇게해서 type에 어떤 유형을 전달 했는지에 따라 cartReducer함수가 실행된다.

일반적으로type이라고 하고 그 유형은 대문자로 적는다. 

(그래야 다른 이들도 읽기 쉽다)

또한 type: "ADD"에는 dipatch함수를 통해 item : 에 매개변수로 받은 item을 전달해 준다. 

type: "REMOVE"에는 지울 아이템을 식별하기 위해 매개변수로 받은 id를 전달해준다. 

 

 

 

 

 

6) cartReducer로 가서 장바구니 항목을 추가하기 위한 로직을 추가한다. 

 

 

 

   목표 : 

 

같은 음식은 그룹화한다(같은 음식을 여러개 담아도 한곳에 출력되고 수량이 추가, 삭제 되도록)

totalAmount도 함께 업데이트 한다. (장바구니 항목의 총 가격)

 

      (1) item을 배열에 대한 item으로 추가한다 

 

 push가 아닌 concat을 사용하도록 하자. 

 

기존 배열에 새 item을 추가한 새 배열을 반환한다.

(이전 데이터의 스냅샷에 새 item을 추가하는 방법은

리액트가 변경을 눈치채지 못하기 때문에

push는 사용하지 않음)

현재 스냅샷의 items와 action에서 받아온 items를 concat하자. 

 

const cartReducer = (state, action) => {
  if (action.type === "ADD") {
    const updatedItems = state.items.concat(action.item);
    const updatedTotalAmount =
    state.totalAmount + action.item.price * action.item.amount;

 

 

 

      (2) 이 action.item에는 모든 필요한 데이터가 있어야 한다.

(수량, 이름, id, 가격 등)

 

 

 

      (3) updatedTotalAmount 수정

action을 통해 추가된 item의 가격과 양을 곱한 값을 기존 state의 totalAmount에 더해준다. 

 

 

 

      (4) 이 Reducer함수의 ADD타입은 배열을 return한다. 

return {
      items: updatedItems,
      totalAmount: updatedTotalAmount,
    };

업데이트 된 item 스냅샷과  업데이트 된 totalAmount 스냅샷을 담은 배열이다.

 

 

나중에 수정할 부분은 

추가된 item이 이미 배열의 일부인지

체크해 그곳에item을 더하는 것이 아닌 수량만 더하는 작업을 해야 하는 것이다.