[React] 1차 프로젝트 장바구니 페이지 1편

전승범·2023년 5월 15일
0
  1. 체크박스
  • 체크박스를 통해 상품 전체 선택, 전체 해제 구현합니다.
  • 상품별 개별 선택, 개별해제(개별선택을 모두 일치 시 전체선택 또는 전체해제로 동작)를 구현합니다.
  • 선택된 제품들의 금액들은 주문명세에서 상품 총금액으로 합해져서 보입니다.
  1. 수량 변경
  • 제품별 금액은 제품정보 내에서 보이고 수량을 변경하면 제품별 금액이 수량에 따른 금액으로 업데이트됩니다.
  1. 서버와의 통신
  • 서버 장바구니 테이블에서 데이터를 전달받아서 장바구니 명세에 렌더링합니다.
  • 구매하려는 제품들을 선택하고 주문결제 버튼을 누르면 선택된 제품들의 데이터를 서버로 전달합니다.

중요하다고 생각한 점

  1. 동작 플로우
    여러 기능을 결합한 코드에서 사용자의 행동을 중심으로 기능들이 목적에 맞게 사용되고 진행되는 게 가장 중요하다고 생각했다.
  2. 단일 책임 원칙
    함수 1개에는 1개의 기능이 들어가야 코드의 가독성이나 유지보수가 좋듯이 컴포넌트와 함수를 한 가지의 명확한 역할을 갖는 단일 책임 원칙에 맞춰서 만들려고 했다.

체크박스

  1. 개별 체크박스
const checkSingle = (checked, id) => {
 	checked
      	? setCheckItems(prev => [...prev, id])
      	: setCheckItems(checkItems.filter(item => item !== id));
};
  
<input
  	className="check-box"
   	type="checkbox"
   	onChange={e => checkSingle(e.target.checked, id)}
    checked={checkItems.includes(id)}
/>
  • 1-1. 개별 체크박스를 선택하면 해당 체크박스의 현재 상태의 event.target.checked(이벤트가 발생할 때 나타나는 값)와 부여해 준 id를 onChange={e => checkSingle(e.target.checked, id)} 함수로 전달한다.
  • 1-2. checkSingle(checked, id) 함수에서는 두 인자를 받아서 checked===T일떄는 checkItems에 해당 체크박스에 id를 추가해서 업데이트하고 checked===F일때는 해당 id를 뺀 나머지를 checkItems로 업데이트한다.
  • 1-3. checkItems에 해당 id가 포함되느냐에 따라 해당 체크박스에 checked={checkItems.includes(id)} T/F가 결정되어서 체크박스 선택의 여부가 판별된다.(체크박스가 1개이면 state 값으로 관리하면 되는데 여러개의 체크박스가 map매서드를 통해 생성되어서 id를 가지고 판별해야 한다.)
  1. 전체 체크박스
const checkAll = checked => {
  	checked
      	? setCheckItems(cartList?.map(item => item.foodId))
      	: setCheckItems([]);
};
   
<input
	id="check-all"
    className="check-box"
    type="checkbox"
    onChange={e => checkAll(e.target.checked)}
    checked={checkItems.length === cartList?.length}
/>
<label htmlFor="check-all" className="select-all">
    전체 선택
</label>
  • 2-1. 전체 체크박스를 선택하면 해당 체크박스의 현재 상태의 event.target.checked(이벤트가 발생할 때 나타나는 값)를 onChange={e => checkAll(e.target.checked)} 함수로 전달한다.
  • 2-2. checkAll(checked) 함수에서는 인자를 받아서 checked===T일떄는 서버에서 받아온 데이터 전체의 id(원래 가지고 있던)를 checkItems로 업데이트하고 checked===F일때는 checkItems에 id를 전부 뺀 빈 배열로 업데이트 한다.
  • 2-3. checkItems에 해당 id가 전부 다 포함돼서 기존 데이터의 id와 일치한다는 것을 length로 확인해서 checked={checkItems.length === cartList?.length} T/F가 결정되어서 체크박스 선택의 유무가 판별된다.
  1. 선택 시 총 결제 금액 표시
let selectList = [];

const totalPrice = orderPrice * quantityChange;

useEffect(() => {
	if (checkItems.includes(id)) {
      	const selectCancle = selectList.filter(item => item.id !== id);
      	selectList = selectCancle;
      	let selectAdd = {};
      	selectAdd = {
        	id: id,
        	sum: totalPrice,
      	};
      	selectList = [...selectList, selectAdd];
    	} else {
      	const selectCancle = selectList.filter(item => item.id !== id);
      	selectList = selectCancle;
    	}
    	const priceSum = selectList.reduce(
      		(accumulator, currentValue) => accumulator + currentValue.sum,
      		0
    	);
    	setProductPrice(priceSum);
  	}, [checkItems]);
    
<div className="price-info order-price">
  	<span>상품 금액</span>
    <span>{productPrice.toLocaleString()}원</span>
</div>

코드에 관해 쓰기 전에 반성부터 합니다. 이거는 하위 컴포넌트에서 작성했으면 안 됐어.........

  • 3-1. 체크박스를 체크할 시 checkItems에 해당 id가 추가된다.
  • 3-2. 그 제품에 대한 정보(제품 id와 금액)를 스프레드 연산자를 사용해서 리스트에 추가한다.
    (전역변수로 리스트를 선언해서 전 데이터가 남아있는 경우가 있다. 이를 막기 위해 fiter매서드 사용해서 불필요한 id 들을 제거했다)
  • 3-3. reduce매서드를 사용해서 리스트에 있는 제품들의 비용의 총합을 구했다.

반성부터 한 이유는 총 결제 금액을 표시하려고 작성한 코드가 map매서드로 생성되는 하위 컴포넌트에 있어서 전체 리스트가 계산되는 게 아니게 됐다. 계속 초깃값으로 리셋되면서 해당 제품에 대한 금액만 표시되고 결과적으로 마지막 제품의 결제 금액이 표시됐다. 디버깅으로는 리스트에 대한 변수를 전역변수로 선언해서 해결했는데 상수 데이터가 아니고서는 전역변수는 예측불가능해서 에러를 발생하기 때문에 지양해야 하므로 리팩토링이 필요하다.

profile
사용자를 위한 프론트엔드 개발자가 되자.

0개의 댓글