[React] 아주 간단한 커피주문 계산 (1)

HYEJIN·2022년 8월 15일
0
post-thumbnail
post-custom-banner

문제: 정해진 예산 5만원이 있고 어떠한 커피를 주문하는지에 따라서 해당 메뉴가 카운팅 되고,
총 가격 버튼을 누를 경우 총 얼마를 지불해야하는지, 거스름돈이 출력된다.

  1. 연습겸 파일을 별도로 분리하지 않고 우선 App.js에 한꺼번에 작성.
    ( 추후에는 분리해서 import export로 사용할 예정 )
import React, { useState } from "react";

function App() {
  return (
    <div className="App">
      <Menu />
    </div>
  );
}

//  -----------------------------함수형 컴포넌트 분리
const Menu = () => {
  const [data, setData] = useState([]);

  const parentFunction = (pass) => {
    console.log(pass);
    const newData = [...data];
    newData.push(pass);
    setData(newData);
  };

  return (
    <>
      <MenuList
        price="4100"
        menu="아메리카노"
        parentFunction={parentFunction}
      />
      <MenuList price="4600" menu="카페라떼" parentFunction={parentFunction} />
      <MenuList
        price="5100"
        menu="캬라멜 마끼아또"
        parentFunction={parentFunction}
      />
      <button>총 가격 </button> :<p>남는 돈: </p>
    </>
  );
};

const MenuList = ({ price, menu, parentFunction }) => {
  const [count, setCount] = useState(0);
  const handleClickAdd = () => {
    setCount((current) => current + 1);

    console.log(count);
    parentFunction({ price, menu, count });
  };
  const handleClickDelete = () => {
    setCount((current) => (current > 0 ? current - 1 : 0));

    console.log(count);
  };
  return (
    <p>
      {`${price}${menu}: ${count}`}
      <button onClick={handleClickAdd}>추가</button>
      <button onClick={handleClickDelete}>감소</button>
    </p>
  );
};

export default App;

1) 문제점
더해진 값에 따라서 버튼을 클릭할 때마다 화면에는 증가하는 값이 잘 출력이 된다.
하지만, count를 바로 찍어도 더해진 값이 출력되지 않는다.
useState의 setCount는 비동기로 동작하기 때문에 그러한 것으로 보인다.

const handleClickAdd = () => {
    setCount((current) => current + 1); // setCount(count + 1);

    console.log(count);
    parentFunction({ price, menu, count });
  };

해당 값(count)이 변할때를 감지하는useEffect() 를 추가하여 해결

import React, { useState, useEffect } from "react";

function App() {
  return (
    <div className="App">
      <Menu />
    </div>
  );
}

//  -----------------------------함수형 컴포넌트 분리

const Menu = () => {
  const MONEY = 50000; // 지정한 회비

  const [data, setData] = useState([]);
  const [payMoney, setPayMoney] = useState(0);
  const [change, setChange] = useState(0);

  const handleClickTotal = (e) => {
    //총 가격 계산
    const total = data.reduce((pre, cur) => {
      return pre + cur.price * cur.count;
    }, 0);

    //가격에 따라서 총 금액과 남는돈 set
    setPayMoney(total);
    setChange(MONEY - total);
  };

  useEffect(() => {
    console.log("Menu useEffect", data);
  }, [data]);

  const handleClick = (pass) => {
    //console.log("pass data:", pass);

    const newData = [...data];
    const exist = newData.find((item) => pass.menu === item.menu);

    //같은 데이터가 존재하지 않는다면 넣어주고
    if (!exist) {
      newData.push(pass);
    }
    //같은 데이터가 존재한다면 count값만 갱신
    else {
      newData.forEach((item, index) => {
        if (item.menu === pass.menu) {
          newData[index].count = pass.count;
        }
      });
    }
    setData(newData);
  };

  return (
    <>
      <MenuList price="4100" menu="아메리카노" handleClick={handleClick} />
      <MenuList price="4600" menu="카페라떼" handleClick={handleClick} />
      <MenuList price="5100" menu="캬라멜 마끼아또" handleClick={handleClick} />
      <button onClick={handleClickTotal}>총 가격 </button> : {payMoney}
      <p>남는 돈: {change} </p>
    </>
  );
};

const MenuList = ({ price, menu, handleClick }) => {
  const [count, setCount] = useState(0);

  //useEffect로 변경하여 부모컴포넌트에 데이터를 전달
  useEffect(() => {
    handleClick({ price, menu, count });
  }, [count]);

  //이것도 왜 2번호출되지 ?
  // useEffect(() => {
  //   console.log("useEffect : ");
  // }, []);

  const handleClickAdd = () => setCount(count + 1);

  const handleClickDelete = () =>
    setCount((current) => (current > 0 ? current - 1 : 0));

  return (
    <p>
      <span>{`${price}${menu}: `}</span>
      <span>{`${count}`}</span>
      <button onClick={handleClickAdd}>추가</button>
      <button onClick={handleClickDelete}>감소</button>
    </p>
  );
};

export default App;

  • useEffect를 추가하여 count 값이 변화함에 따라서 부모 컴포넌트에 커피의 카운팅을 전달한다.
  • useState로 총 지불해야할 금액과 남은 금액을 변수로 담아 출력한다.
    ㄴ 버튼을 누를 경우 총 가격을 계산 후 setPayMoney,setChange를 통해 값을 변경한다.

2) 문제점 / useEffect 의 동작


useEffect는 랜더링 될 때와 값이 변경될때 호출이되는 것으로 알고있는데,
처음 랜더링될때 이것이 2번 호출되는 것으로 보이며,
<MenuList>의 마지막 요소가 data로 미리 들어가면서 한번더 useEffect가 호출되는 문제점을 볼 수 있었다.

콘솔로 찍어보지 않았을 때는 제대로 동작하는걸로 착각할 수 있다.
현재 코드는 뭔가 이상해보인다.

post-custom-banner

0개의 댓글