React로 계산서 구현하기

Universe·2023년 3월 9일
0

☀️

깃허브
별로 어려운 거 아니었는데 왜이렇게 긴장했을까
😢




🌕

요구된 상황은 이렇다.
서버에서 받아온 데이터 (라고 가정한다) 에는
상품의 가격, 이름, 상품 id 같은 것이 들어 있는데,
버튼을 누르면 가격표에 항목이 추가되고, 만약 이미 계산서에 해당 상품이 존재하면
카운팅을 추가하는 방식이다.
장바구니? 계산서? 같은 느낌의 구현사항인데
너무 어렵게 생각했던 것 같다.

뒤늦게 깨달은 풀이 방식은 다음과 같다.

basket 배열에 product 추가하기

{products.map((product) => {
        return (
          <button
            key={`item${product.id}`}
            onClick={() => onClickHandler(product.id)}
          >
            {product.name}
          </button>
        );
      })}

products 는 서버에서 받아온 상품 데이터.
데이터를 매핑해서 버튼을 추가한다. 그 버튼을 누르면
onClickHandler 로 해당 id를 보내서

  const onClickHandler = (itemId) => {
    const itemIndex = basket.findIndex(
      (basketItem) => basketItem.id === itemId
    );
    if (itemIndex === -1) {
      setBasket([...basket, { id: itemId, count: 1 }]);
    } else {
      const copyBasket = [...basket];
      copyBasket[itemIndex].count += 1;
      setBasket(copyBasket);
    }
  };

basket state에서 findIndex 메소드로 전송한 id와 같은 id를 찾는다.
findIndex의 값이 -1이라면 (데이터가 없다면) id와 count를 key로 갖는 객체를 만들어
basket state에 추가한다.
findIndex의 값이 -1이 아니라면 해당 index를 찾아 count 값에 +1을 해서
basket state를 수정한다.
basket 배열을 전개 연산자로 깊은복사 한 다음 수정 후 set 함수를 실행해준 모습.

서버 데이터를 기반으로 basket state 매핑하기

이 부분에서 고민을 많이했다.
"장바구니에 데이터가 담겨있는 채로 서버 데이터의 이름이나 가격이 바뀌면 어떤 문제가 발생할까요 ?"
라는 질문에 대답을 못했었기 때문에.

          <ul className="item-list">
            {basket.map((basketItem) => {
              const product = findProductById(basketItem);
              const price = calculateProductPrice(product, basketItem.count);
              return (
                <li key={`basket${basketItem.id}`}>
                  <span>{product.name}</span>
                  <span>{basketItem.count}</span>
                  <span>{price}</span>
                </li>
              );
            })}
          </ul>

basket state를 map 해준다.
서버 데이터를 기반으로 name과 price를 계산해야 하므로 추가적인 로직이 필요하다.

const findProductById = (basketItem) => {
    return products.find((p) => p.id === basketItem.id);
  };

const calculateProductPrice = (product, count) => {
    return product.price * count;
  };

id를 기반으로 products에서 같은 id를 가진 product를 찾는 함수와
product를 기반으로 저장된 count를 곱해 price를 계산하는 함수를 추가적으로 만들었다.
JSX 매핑 로직에서 추가적인 연산이 있으면 비효율이 발생하게 되므로
함수로 따로 빼주었는데 조금 더 깔끔한 로직이 있었을까 생각하게 된다.

총 합계 계산하기

  const calculateTotalPrice = () => {
    let result = 0;
    basket.forEach((basketItem) => {
      const product = findProductById(basketItem);
      result += calculateProductPrice(product, basketItem.count);
    });
    return result;
  };

매핑로직 내부에서 어떻게 할 방법을 찾지 못해서 추가적으로 함수를 만들었다.




⭐️

기회는 준비된 사람에게 온다고 하는데,
아직 기회를 받아들일만큼 준비하지 못한 것 같다.
정말 좋은 기회였을텐데 너무 아쉽다.

profile
Always, we are friend 🧡

0개의 댓글