내가 맡은 장바구니에는 총 4개의 컴포넌트가 있다.
최 상위 컴포넌트 Cart / 상품들 list를 담을 CartList / 상품 개별 컴포넌트 CartProduct
그리고 CartList와 같은 선상에 있는 계산서 컴포넌트, CartPayment 컴포넌트가 있다.
체크박스는 최 하위 컴포넌트인 CartProduct 컴포넌트에 하나씩 있고, 그 상위 컴포넌트인 CartList에 모두선택 체크박스가 있다.
그 체크 여부에 따라 상품 가격의 변동을 CartPayment 컴포넌트에 넘겨주어야 하는 상황인데,
그렇게 되면 최 상위 컴포넌트인 Cart 컴포넌트에서 모든 값을 관리해야 한다.
서버와 통신하기 전 먼저 임시 데이터를 만들었고, 컴포넌트 안에서 useState로 관리하고자 하였다.
그리고 Cart 컴포넌트에서 체크박스 상태를 관리할 함수를 하나 만들어 두고
각각 CartList와 CartProduct 컴포넌트로 넘겨준다.
그리고 이런 식으로 전체선택 체크박스와 개별의 체크박스에서 onChange 속성으로 props로 넘겨준 함수를 실행시켜 id와 check 여부(true, false값)을 가져온 후
const checkValueHandle = (id, checked) => {
const productIdx = products.findIndex(product => product.id === id);
if (typeof id === 'number') {
const newProducts = [...products];
newProducts[productIdx].isChecked = checked;
setProductUpdate(newProducts);
} else if( id === "cartCheckAll") {
const newProducts = [...products];
newProducts.map(product => (product.isChecked = checked));
setProductUpdate(newProducts);
}
};
클릭한 곳의 id값을 가져와서 id값이 숫자라면 개별 컴포넌트의 체크박스이므로
배열 복사를 한 후 그 안의 데이터에서 해당하는 id가 있는 객체에 체크 여부를 현재 체크 상태로 업데이트 한다.
(여기서도 시간이 꽤 걸렸던 것이 배열 복사를 하지 않으면 원본 데이터가 단 하나의 true false 값으로 바뀌어 버린다. 따라서 안전하게 배열 복사를 한 후에 진행한다.)
이렇게 해서 만일 아이디값이 cartCheckAll라면 전체 선택 체크박스이므로,
복사한 데이터 배열에 map을 돌려서 모든 객체의 체크여부를 전체선택 체크여부와 동일하게 바꿔준 후 원본 데이터를 업데이트 시킨다.
여기까지만 한다면 그 다음은 어렵지 않다.
원본 데이터에서 체크 여부가 true 인 것을 filter함수를 이용해 골라낼 수 있고, 이 데이터들로 선택적 삭제가 가능하며(골라낸 후 남은 것들만 원본 데이터로 업데이트 시켜주면 된다.)
체크된 것 들만 따로 모아 가격 총액을 계산해 다른 컴포넌트로 넘겨줄 수 있다.
또한 전체 선택 체크박스의 경우
const isAllCheck =
products.filter(product => product.isChecked === true).length ===
products.length
? products.length === 0
? false
: true
: false;
삼항 연산자를 통해 true false 값을 리턴시키고 이 변수를 전체 체크박스의 checked 속성으로 넣어주면 된다.