안녕하세요

1주차 과제 장바구니(2) - 장바구니에 추가, 삭제, 수량 조절, 전체가격 표시 본문

복습스터디과제

1주차 과제 장바구니(2) - 장바구니에 추가, 삭제, 수량 조절, 전체가격 표시

sakuraop 2023. 1. 14. 02:11

[1주차 과제 장바구니 사이트] (2023-01-13 ~ 2023-01-18 약 일주일)

 

React App

 

youngentry.github.io

 

 


장바구니에 제품 추가하기

1. 장바구니를 렌더링하기 위한 리스트를 만든다.

  const [cartList, setCartList] = useState([]);

 

2. 삼항연산자를 이용해 장바구니에 상품이 있을 때, 없을 때를 나누어 표시한다.

                  {cartList.length ? (
                    cartList.map((cartItem, index) => {}
                  ) : (
                    <span>장바구니에 담긴 상품이 없습니다.</span>
                  )}

3. 장바구니에 추가 버튼을 클릭하면 선택된 제품의 id를 전달하는 함수를 만든다.

              <Button variant="primary" onClick={() => addItemIntoCartList(data.id)}>
                장바구니에 추가
              </Button>

 

4. find() 메서드를 이용하여 선택된 제품의 id와 일치하는 제품을 데이터에서 찾는다.

  // ----- 장바구니에 제품 추가하기 -----
  const [cartList, setCartList] = useState([]);
  const [idSelectedItem, setIdSelectedItem] = useState(null);
  const addItemIntoCartList = (id) => {
    // id와 같은 제품을 데이터에서 찾기
    setIdSelectedItem(id);

    const itemFoundByIdFromShoesData = shoesData.find((shoes) => shoes.id === id);
  // ----- 장바구니에 제품 추가하기 -----
 
    const itemFoundByIdFromShoesData = shoesData.find((shoes) => shoes.id === id);

=> find() 메서드를 이용한 id와 일치하는 데이터 찾기

 

5. 장바구니 데이터에는 수량을 더하여 업데이트한다.

  // ----- 장바구니에 제품 추가하기 -----
  const [cartList, setCartList] = useState([]);
  const [idSelectedItem, setIdSelectedItem] = useState(null);
  const addItemIntoCartList = (id) => {
    // id와 같은 제품을 데이터에서 찾기
    setIdSelectedItem(id);

    const itemFoundByIdFromShoesData = shoesData.find((shoes) => shoes.id === id);

    // cartList 데이터 업데이트하기 (있으면 수량++, 없으면 상품목록에 추가)
    if (itemFoundByIdFromShoesData.amount) {
      return (itemFoundByIdFromShoesData.amount += 1);
    }
    itemFoundByIdFromShoesData.amount = 1;
    setCartList([...cartList, itemFoundByIdFromShoesData]);
  };

  // ----- 장바구니에 제품 추가하기 -----
    if (itemFoundByIdFromShoesData.amount) {
      return (itemFoundByIdFromShoesData.amount += 1);
    }

=> 데이터의 속성에 amount가 존재한다면 값을 +1 해준다. 

 

    itemFoundByIdFromShoesData.amount = 1;

=> 그렇지 않을 때는 데이터의 속성에 amount = 1 이라는 값을 추가한다. 

 

    setCartList([...cartList, itemFoundByIdFromShoesData]);

=> cartList를 업데이트한다.


수량 조정 기능 구현하기

1. +를 클릭하면 숫자가 올라가고, -를 클릭하면 숫자가 내려가는 함수를 만든다.

            <Button variant="primary" onClick={() => plusCartItemAmount(cartItem.id, false)}>
              -
            </Button>
            <Button variant="light">{cartItem.amount}</Button>
            <Button variant="primary" onClick={() => plusCartItemAmount(cartItem.id, true)}>
              +
            </Button>

=> plusCartItemAmount 함수는 id와 boolean 값을 전달한다.

 

2. cartList의 데이터를 업데이트한다.

  // ----- 장바구니 제품 "+", "-"로 수량 바꾸기 -----
  const plusCartItemAmount = (id, boolean) => {
    setIdSelectedItem(id);
    const itemFoundByIdFromCartList = cartList.find((cartItem) => cartItem.id === id);
    // 수량을 1더하기 한다.
    if (boolean) {
      return (itemFoundByIdFromCartList.amount += 1);
    }

    // 수량이 1이상일 때 -1
    if (itemFoundByIdFromCartList.amount > 0) {
      itemFoundByIdFromCartList.amount -= 1;
    }
  };
  // ----- 장바구니 제품 "+", "-"로 수량 바꾸기 -----
 
    const itemFoundByIdFromCartList = cartList.find((cartItem) => cartItem.id === id);

=> 선택한 제품의 id와 일치하는 제품을 cartList에서 찾는다.

 

    if (boolean) {
      return (itemFoundByIdFromCartList.amount += 1);
    }

=> +버튼을 누르면 true를 전달 받고, 해당 제품 데이터의 amount 속성을 +1로 업데이트한다.

=> -버튼을 누르면 false를 전달받아 +1이 동작하지 않는다.

 

    // 수량이 1이상일 때 -1
    if (itemFoundByIdFromCartList.amount > 0) {
      itemFoundByIdFromCartList.amount -= 1;
    }

=> -버튼을 눌렀을 때 수량이 마이너스가 되지 않도록 0보다 클 때만 amount 속성을 -1로 업데이트한다.

 

3. 장바구니 기능과 관련된 함수가 동작할 때 대부분 id를 이용하므로, id state가 변할 때마다 렌더링 하도록 초기화한다.

  // 장바구니 렌더링용 state 변화감지
  useEffect(() => {
    setIdSelectedItem(null);
    console.log(cartList);
  }, [idSelectedItem]);

장바구니 리스트에서 삭제하기

1. 버튼을 클릭하면 id를 전달하는 함수를 만든다.

                <CloseButton onClick={() => removeCartItem(cartItem.id)} />

 

2. 선택한 제품을 cartList에서 제외한다.

  // ----- 장바구니에서 선택한 제품 삭제하기 -----
  const removeCartItem = (id) => {
    const tempCartList = [...cartList];
    const itemFoundByIdFromCartList = tempCartList.find((tempCartItem) => tempCartItem.id === id);

    // 제품 배열에서 제외
    tempCartList.splice(itemIndexSelectedByIdFromCartList, 1);

    setCartList([...tempCartList]);
  };
  // ----- 장바구니에서 선택한 제품 삭제하기 -----

 

    const itemIndexSelectedByIdFromCartList = tempCartList.findIndex((tempCartItem) => tempCartItem.id === id);

=> find()메서드를 이용하여 id로 해당 제품의 index를 찾는다.

 

    tempCartList.splice(itemIndexSelectedByIdFromCartList, 1);
 
    setCartList([...tempCartList]);

=> splice() 메서드를 이용하여 배열에서 해당 제품을 배열에서 제외한 데이터로 업데이트한다.

 

3. 수량 초기화하기

제품에 amount 속성이 업데이트 되어있었기 때문에 이를 0으로 초기화하지 않으면

제품을 다시 추가할 때 오류가 발생한다.

    // cartList 데이터 업데이트하기 (있으면 수량++, 없으면 상품목록에 추가)
    if (itemFoundByIdFromShoesData.amount) {
      return (itemFoundByIdFromShoesData.amount += 1);
    }
    itemFoundByIdFromShoesData.amount = 1;
    setCartList([...cartList, itemFoundByIdFromShoesData]);

 

    if (itemFoundByIdFromShoesData.amount) {

=> amount의 값을 0으로 초기화해주면 조건이 false가 되어 +1 을 하는 것이 아닌

 

    itemFoundByIdFromShoesData.amount = 1;
    setCartList([...cartList, itemFoundByIdFromShoesData]);

=> 제품 추가하기가 실행된다.

 

  // ----- 장바구니에서 선택한 제품 삭제하기 -----
  const removeCartItem = (id) => {
    const tempCartList = [...cartList];
    const itemIndexSelectedByIdFromCartList = tempCartList.findIndex((tempCartItem) => tempCartItem.id === id);
    const itemFoundByIdFromCartList = tempCartList.find((tempCartItem) => tempCartItem.id === id);

    // 수량 초기화
    itemFoundByIdFromCartList.amount = 0;
    // 제품 배열에서 제외
    tempCartList.splice(itemIndexSelectedByIdFromCartList, 1);

    setCartList([...tempCartList]);
  };
  // ----- 장바구니에서 선택한 제품 삭제하기 -----

 

    const itemFoundByIdFromCartList = tempCartList.find((tempCartItem) => tempCartItem.id === id);

=> find() 메서드를 이용하여 id가 일치하는 제품을 찾아

 

    itemFoundByIdFromCartList.amount = 0;

=> amount 속성을 0으로 초기화한다.


장바구니 전체 가격 나타내기

 

1. 전체 가격을 구하기 위한 함수를 만든다.

                <strong>총 액수 : {getPriceTotalFromCartList(cartList)}원</strong>

 

2. cartList의 아이템들의 price 속성과 amount 속성의 값을 곱한 값을 반환한다.

  // ----- 장바구니에 담긴 아이템 전체가격 -----
  const getPriceTotalFromCartList = (itemList) => {
    let priceTotal = 0;

    itemList.forEach((item) => {
      priceTotal += item.price * item.amount;
    });

    return priceTotal;
  };
  // ----- 장바구니에 담긴 아이템 전체가격 -----

 

3. 1,000과 같이 세자리 수마다 콤마를 찍는 함수를 만든다.

/** 
  숫자 세자리마다 콤마 찍기 위함 ex) 1000 => 1,000
  @param number
*/
const getPriceComma = (price) => {
  return price.toLocaleString("ko-KR");
};

 

.toLocaleString("ko-KR")

=> toLocaleString() 메서드를 이용하면 입력받은 숫자(1000)를 세자리 마다 콤마를 넣어(1,000) 표기할 수 있다 

 

4. 구한 전체 값에 콤마를 찍는 함수를 실행한 값을 반환하도록 한다.

  // ----- 장바구니에 담긴 아이템 전체가격 -----
  const getPriceTotalFromCartList = (itemList) => {
    let priceTotal = 0;

    itemList.forEach((item) => {
      priceTotal += item.price * item.amount;
    });

    priceTotal = getPriceComma(priceTotal);
    return priceTotal;
  };
  // ----- 장바구니에 담긴 아이템 전체가격 -----

추가목표
컴포넌트를 분리하여 렌더링 범위를 작게 만들기

차후에 리덕스로 이식할 때는 cartList 데이터를 별도로 생성하여

selectedId state가 변할 때마다 전체 화면을 렌더링하지 않도록 한다.