DH의 개발 공부로그
[React] 리액트 Checkbox 문제 해결하기! - 전체 선택/해제 기능 본문

문제 발견
이전의 작업을 했던 리액트 Set
을 이용한 checkbox
를 다루었던 코드에서 문제점이 있었습니다.
[React] 리액트에서 Set 이용한 Checkbox 상태관리하기!
이전의 코드를 확인하고 싶으면 다음과 같습니다. 이전 소스코드 확인하기
문제점이 무엇인지 확인을 해보면, 우선 전체선택과 개별선택
이 있는
체크박스의 기능들은 다음과 같아야 합니다.
- 개별 체크박스 선택/해제 기능
- 전체 선택을 클릭 시 전체 선택/해제 변경 기능
- 전체 선택 시에 하나라도 체크가 해제되면 전체 선택 박스 체크 해제
- 모든 체크박스가 선택될 경우 전체 선택 박스 체크 활성화
이렇게 4가지의 경우가 충족이 되어야 합니다.
하지만 위의 코드에서 1번과 2번의 조건은 충족이 되지만, 3번과 4번의 기능들은 충족하지 못하는 문제가 있었습니다.
그렇기 때문에 다음과 같이 코드를 수정했습니다.
코드 수정
1. 배열을 이용
Set
을 이용하는 방법도 좋은 방법이라고 생각은 하지만,
코드를 더욱 줄이고, 배열을 이용하여 특별한 메서드 없이 쉽게 다룰 수 있다고 판단하여 배열로 변경을 하였습니다.
const [checkItems, setCheckItems] = useState([])
2. 코드 단축 - checkItemHandler(), allCheckedHandler()
Set
을 이용했을 때는 Set
의 메서드를 이용해서 추가 또는 삭제 후 다시 setCheckItems
에 넣어주는 형태 였다면,
배열을 이용해서 간편하고 단순하게 다음과 같이 작업을 했습니다.
const checkItemHandler = (id, isChecked) => {
if (isChecked) {
setCheckItems((prev) => [...prev, id]) // 불변성을 지키기 위한 원본 배열을 복사 후 추가
} else {
setCheckItems(checkItems.filter((item) => item !== id))
// 현재 checkItems의 배열에서 해당 id를 제외한 새로운 배열 반환
}
}
기존 코드에서는 CheckBoxList
, CheckBox
컴포넌트 양쪽에서 allCheckedHandler()
를 만들어
작업을 하면서 같은 이름의 함수로 인한 가독성을 헤치는 작업을 했던 부분을 제거 하고,CheckBoxList
에 다음과 같은 코드로 단축을 했습니다.
const allCheckedHandler = (e) => {
if (e.target.checked) {
setCheckItems(checkList.map((item) => item.id))
} else {
setCheckItems([]);
}
console.log(`allCheck = `, e.target.checked)
}
3. 개별 선택 해제 시 전체 선택 해제
이 부분이 가장 중요하다고 생각이 됩니다.
이 기능 때문에 코드를 수정을 했기 때문입니다.
코드는 다음과 같이 수정을 했습니다.
// CheckBoxList.jsx
<header>
<label>
<input type="checkbox" onChange={allCheckedHandler}
checked={checkItems.length === checkList.length ? true : false}/>
전체선택
</label>
</header>
<div>
{
checkList.map((item) => (
<CheckBox key={item.id} id={item.id} checkItemHandler={checkItemHandler}
checked={checkItems.includes(item.id) ? true : false} />
))
}
</div>
원래는 checked
에 useState
를 이용해서 상태를 관리했는데 삼항연산자로 수정을 하면서 문제를 해결을 했습니다.
checked={checkItems.length === checkList.length ? true : false}
// checkItems, 체크된 아이템의 개수와 현재 데이터 개수가 다를 경우 선택 해제 (하나라도 해제 시 선택 해제)
{
checkList.map((item) => (
<CheckBox key={item.id} id={item.id} checkItemHandler={checkItemHandler}
checked={checkItems.includes(item.id) ? true : false} />
// checkItems, 체크된 아이템 배열에 해당 id가 있으면 체크 없으면 해제
))
}
기존 코드에서는 다음과 같이 useEffect
를 사용해서 문제가 있었는데 위의 코드와 같이 수정하면서
문제를 해결 했습니다.
const allCheckHandler = () => setChecked(isAllChecked);
useEffect(() => allCheckHandler(), [isAllChecked])
// useEffect 훅으로 isAllChecked 변경 시 체크함수를 활성화 해서 전체 선택 후 개별 선택 변경 시 문제 발생
작업 결과

'React' 카테고리의 다른 글
[React] 리액트 아이콘 (React-icons) 적용해서 사용하기! (0) | 2023.04.04 |
---|---|
[React] 리액트 console.log() 두 번씩 찍히는 이유? - 렌더링이 두 번 되는 이슈 (0) | 2023.03.24 |
[React, TypeScript] 리액트 + 타입스크립트에서 Props 전달하는 방법 - IntrinsicAttributes 오류 (0) | 2023.03.14 |
[React] 리액트 라우터 - RouterProvider와 CreateBrowserRouter (0) | 2023.03.10 |
[React] Vite 사용하기! (0) | 2023.03.07 |