[React] CheckBox 커스텀하기, 전체선택 구현

lyshine·2023년 10월 17일
0

React

목록 보기
5/6

이번에 프로젝트를 진행하면서 만든 CheckBox 구현기를 적어보려고 한다!
처음에 CheckBox를 구현하려고 했을때는 간단해 보였지만, 고민해봐야 될 부분들이 꽤 있어서 생각보다 구현하는데 시간이 걸렸다.

컴포넌트 구현

먼저 구현된 Checkbox 컴포넌트 코드는 다음과 같다

  • text와 onChange, checked props를 받아온다.

  • text는 체크박스에 표현될 라벨, onChange는 체크박스의 변경을 제어하는 함수, checked는 체크 박스가 체크되었는지 여부를 알 수 있는 input태그의 checked 속성으로 boolean값을 가진다.

  • 체크박스 컴포넌트 구현

import { InputHTMLAttributes } from "react";

import { CheckboxContainer, CheckboxInput, CheckboxText } from "./style";

interface CheckBoxProps extends InputHTMLAttributes<HTMLInputElement> {
  text?: string;
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
  type?: string;
}

export default function CheckBox({
  id,
  name,
  text,
  onChange,
  type,
  checked,
}: CheckBoxProps) {
  return (
    <CheckboxContainer>
      <CheckboxInput
        type="checkbox"
        id={id}
        name={name}
        onChange={onChange}
        $isCircle={type === "circle"}
        checked={checked}
      />
      <CheckboxText htmlFor={id}>{text}</CheckboxText>
    </CheckboxContainer>
  );
}

전체선택/ 개별선택 체크박스 로직 구현

  • 초기 상태가 빈 배열인 checkedListById 체크 목록을 만들고, 체크박스의 체크 목록 여부는 해당 항목의 id값으로 결정된다.
  • 상품리스트 배열의 각 item의 id값을 이용해 체크박스를 제어할 수 있도록 구현했다.
  • input[type=”checkbox”]의 checked속성을 이용하여 체크되었는지 확인하고 체크 여부를 통해 checkedListById 상태에 추가/제거하는 방식이다.

handleCheckChange, handleAllCheck 함수 설명

  • handleCheckChange : 개별 체크박스를 제어하는 함수
  1. 체크박스의 id를 인자로 받아, 해당 id가 체크 목록에 포함되었는지를 확인한다.
  2. 포함되지 않은 id, 즉 선택되지 않은 id라면 체크 목록에 추가하고 선택되지 않은 id이면 해당 id를 체크 목록에서 제거한다.
  • handleAllCheck : 전체선택 체크박스를 제어하는 함수
  1. 체크박스의 checked 속성을 인자로 받아, 모두 체크되었는지 여부를 확인한다. 이때 체크목록배열의 길이와 항목의 길이를 비교하여 체크여부를 알 수 있다.
  2. 전체선택을 클릭하면, 현재 체크목록으로 있는 모든 항목의 id를 체크 목록에 추가해준다.
  3. 전체선택을 해제하면, 체크 목록을 빈 배열로 만들어 전체 선택이 해제되도록 한다.
const [checkedListById, setCheckedListById] = useState<number[]>([]);
const checkedNum = checkedListById.length;

const handleCheckChange = (id: number) => {
  const isChecked = checkedListById.includes(id);

  if (isChecked) {
    setCheckedListById((prev) => prev.filter((el) => el !== id));
  } else {
    setCheckedListById((prev) => [...prev, id]);
  }
};

const handleAllCheck = ({
  target: { checked },
}: {
  target: { checked: boolean };
}) => {
  if (checked) {
    setCheckedListById(mockData.map((item: Item) => item.id));
  } else {
    setCheckedListById([]);
  }
};

적용

  • 전체선택 체크박스
<CheckBox
  text="전체선택"
  onChange={handleAllCheck}
  checked={checkedNum === mockData.length}
/>
  • 개별선택 체크박스
{products.map((item) => (
    <ProductItem key={item.id}>
    <CheckBox
      onChange={() => handleCheckChange(item.id)}
      checked={checkedListById.includes(item.id)}
    />
		...
  </ProductItem>
))}

0개의 댓글