본문 바로가기
💻CODING/react. vue

[react] 장바구니 추가, 삭제, 전체 삭제 기능 구현

by 코딩하는 갓디노 2021. 9. 10.

react 장바구니 기능

 

예제는 패스트캠퍼스의 "이웅재"님의 강의를 들으면서 공부한 내용입니다.

구현 내용

const [orders, setOrder] = useState([{id: ' ', quantity: 0}]) 의 형식으로 state 관리
장바구니에 상품 추가
선택한 상품 삭제, 전체 장바구니 삭제
사용한 web API: find(), map(), filter() 

 

구현 영상

 

상품 리스트 컴포넌트

<div>
    {prototypes.map((prototype) => {
    	const { id, thumbnail, title, price, desc, picUrl } = prototype;
    	const onAdd = () => {addToOrder(id)} //** 이 부분에서 클릭이벤트로 해당 id 보내줌
    	
       return (
   		 <div key={id}>
   		   <a href={picUrl} target="_BLANK" rel="noreferrer">
   		 	<div>
               <video
                autoPlay
                loop
                playsInline
                style={{ objectFit: "contain" }}
                src={thumbnail}
              />
      		</div>
          </a>
       <div>
        <div>
         <div onClick={onAdd}> 
           <i className="icon" />
         </div>
         {title}
        </div>
        <p>$ {price}</p>
        <p>{desc}</p>
       </div>
     </div>
     );
    })}
 </div>

 

상품 추가 기능

option1

const [orders, setOrders] = useState([]); //주문 상품

//[{id: x, quanity: x}]
const addToOrder = useCallback((id) => {
  setOrders(orders => { //기존의 orders를 받아서 새로운 orders return             
    const find = orders.find(one => one.id === id) //id가 첫번째 요소, 없을시 undefined
    if (find === undefined) { //처음 add시
      return [...orders, {
        id: id,
        quantity: 1
      }] //새로운 요소 추가
    } else { //기존 added된게 있을때
      return orders.map(one => {
        if (one.id === id) { //개수 부분 수정
          return {
            id,
            quantity: one.quantity + 1
          }
        } else {
          return one;
        }
      })
    }
  });
}, []);

 

option2 - 삼항연산자로 코드 리팩토링

const addToOrder = useCallback((id) => {
  setOrders(orders => { //기존의 orders를 받아서 새로운 orders return             
    const find = orders.find(one => one.id === id) //id가 첫번째 요소, 없을시 undefined
    if (find === undefined) { //처음 add시
      return [...orders, {
        id: id,
        quantity: 1
      }] //새로운 요소 추가
    } else { //기존 added된게 있을때
      return orders.map(one => one.id === id ? { id, quantity: one.quantity + 1 } : one);
    }
  });
}, []);

 

장바구니 컴포넌트

export default function Orders() {
  const totalPrice = useMemo(() => { //장바구니 담긴 상품 최종 가격
    return orders
      .map((order) => {
        const { id, quantity } = order;
        const prototype = prototypes.find((p) => p.id === id); //가격을 찾기위해 해당 id의 prototypes에 접근
        if (prototype) {
          return prototype.price * quantity;
        } else { return false }

      })
      .reduce((l, r) => l + r, 0); //map으로 return된 값들 전부 더함
  }, [orders, prototypes]); //orders가 변할때마다 렌더링

  if (orders.length === 0) { //주문 내역이 없을시 보여주는 화면
    return (
      <aside>
          <div>장바구니가 비어있습니다.</div>
      </aside>
    )
  }

  return (
    <aside>
      <div>
          {orders.map((order) => {
            const { id } = order;
            //해당 order의 자료를 prototypes 데이터에서 찾아서 접근
            const prototype = prototypes.find((p) => p.id === id); 
            
            return (
              prototype && <>
                <div key={id}>
                    <video src={prototype.thumbnail} />
                </div>
                <div>{prototype.title} x {order.quantity}</div>
                <div className="action">$ {prototype.price * order.quantity}</div>
                  <button onClick={() => remove(id)}>
                    <i className="icon" />
                  </button>
                </div>
              </>
            );
          })}
        </div>
        <div className="total">
          <div className="item">
            <div>Total</div>
            <div>$ {totalPrice}</div>
            <button className="btn" onClick={removeAll}>
              <i className="icon" />
            </button>
          </div>
      </div>
    </aside>
  );
}

 

특정 상품 삭제 / 상품 전체 삭제

const remove = useCallback((id) => { //선택 상품 삭제
  setOrders(orders => {
    return orders.filter(one => one.id !== id);
  })

}, []);
const removeAll = useCallback((id) => { //전체 삭제 
  setOrders([]); //빈 배열로 만들어줌
}, []);

 

 

 

반응형

댓글