React.js & Next.js

리액트에서 다수의 체크 박스 다루기

준희닷 2022. 9. 13. 22:25

 

우리는 사용자에게 선택지를 제공할 때 <input type=”radio”> 또는 <input type=”checkbox”> 등을 사용한다. radio의 경우 여러 개의 선택지 중 한 가지를 선택해야 할 때 주로 사용하고, checkbox의 경우 여러 개의 선택지 중 중복 선택이 가능할 때 주로 사용된다고 볼 수 있다.

 

<form>을 통해 유저의 인터렉션(클릭 이벤트)을 캐치하여 데이터를 생성해야 할 때, checkbox는 사용자의 선택을 배열로 관리하여 데이터화한 이후, 서버 또는 데이터 베이스에 저장하기 유용한 자료구조이다.

이번에는 리액트 프레임워크에서 <input type=”checkbox”> 를 통해 체크 여부를 배열 데이터로 관리하는 방법을 배워볼까 한다.

준비

기본적으로 string으로 구성된 더미 배열을 생성한다. jsx 문법 내부에 생성할 경우, 지속적으로 리 렌더링 되며 초기화될 수 있으므로 컴포넌트 윗부분에 작성하도록 한다.

const checkBoxList = ['Apple', 'Banana', 'Pare', 'Grape', 'Melon', 'Water Melon', 'Pineapple '];

해당 checkBoxList의 더미 데이터를 바탕으로 Array.prototype.map() 메서드를 통해 화면에 렌더링한다.

<div className='checkbox-group'>
  {checkBoxList.map((item, idx) => (
    <div className='checkbox' key={idx}>
      <input
        type='checkbox'
        id={item}
      />
      <label htmlFor={item}>{item}</label>
    </div>
  ))}
</div>

체크박스 이해하기

기본적으로 checkbox의 check 여부는 <input type=”checkbox” check={???}/> input의 프로퍼티 중 하나인 check 속성을 통해 알 수 있다. input의 해당 check 속성 중 체크된 상태의 element를 배열로 관리하는 로직을 구성해야 한다.

checkBoxList 배열 중 check 된 element를 관리할 useState를 생성한다.

const [checkedList, setCheckedList] = useState<string[]>([]);

또한 해당 element가 체크된 상태인지 파악하기 위한 useState를 생성한다.

const [isChecked, setIsChecked] = useState(false);

이제 input을 클릭했을 때, checkedList라는 useState 배열에 해당 element가 포함되어있지 않다면 추가하고 checkedList 배열에 이미 포함되어 있다면 해당 배열에서 제거하는 handler 함수를 만들어 준다.

  const checkedItemHandler = (value: string, isChecked: boolean) => {
    if (isChecked) {
      setCheckedList((prev) => [...prev, value]);

      return;
    }

    if (!isChecked && checkedList.includes(value)) {
      setCheckedList(checkedList.filter((item) => item !== value));

      return;
    }

    return;
  };

  const checkHandler = (e: React.ChangeEvent<HTMLInputElement>, value: string) => {
    setIsChecked(!isChecked);
    checkedItemHandler(value, e.target.checked);
  };

React.ChangeEvent<HTMLInputElement> 내부 이벤트를 통해 해당 Input 엘리먼트가 체크됐는지 여부를 파악할 수 있다.

 

해당 checkHandler를 input에 연결한다.

<div className='checkbox-group'>
  {checkBoxList.map((item, idx) => (
    <div className='checkbox' key={idx}>
      <input
        type='checkbox'
        id={item}
        checked={checkedList.includes(item)}
        onChange={(e) => checkHandler(e, item)}
      />
      <label htmlFor={item}>{item}</label>
    </div>
  ))}
</div>

코드를 보면 checked 프로퍼티에 checkedList.includes(item) includes라는 메서드를 통해 체크 여부를 파악하는 것을 알 수 있다. includes는 Array.prototype.includes()로 내부에 해당 요소(element)가 존재할 경우 (포함된 경우) true를 반환한다 우리는 map을 통해 input을 렌더링하고 있기 때문에 각 요소(element) 별로 checkedList에 포함되어 있다면 checked 상태로 보일 것이다.

 

해당 로직에 form 태그를 연결하여 결과적으로 원하는 값이 잘 담기는지 확인한다.

 const onSubmit = useCallback(
    (e: React.FormEvent<HTMLFormElement>) => {
      e.preventDefault();

      console.log('checkedList:', checkedList);
    },
    [checkedList]
  );

...

<div>
  <h1>Fruits list</h1>

  <form onSubmit={onSubmit}>
    <div className='checkbox-group'>
      {checkBoxList.map((item, idx) => (
        <div className='checkbox' key={idx}>
          <input
            type='checkbox'
            id={item}
            checked={checkedList.includes(item)}
            onChange={(e) => checkHandler(e, item)}
          />
          <label htmlFor={item}>{item}</label>
        </div>
      ))}
    </div>

    <button type='submit'>submit</button>
  </form>
</div>

결과 확인하기

최종 코드

import { useCallback, useState } from 'react';

const checkBoxList = ['Apple', 'Banana', 'Pare', 'Grape', 'Melon', 'Water Melon', 'Pineapple '];

const CheckBoxes = () => {
  const [checkedList, setCheckedList] = useState<string[]>([]);
  const [isChecked, setIsChecked] = useState(false);

  const checkedItemHandler = (value: string, isChecked: boolean) => {
    if (isChecked) {
      setCheckedList((prev) => [...prev, value]);

      return;
    }

    if (!isChecked && checkedList.includes(value)) {
      setCheckedList(checkedList.filter((item) => item !== value));

      return;
    }

    return;
  };

  const checkHandler = (e: React.ChangeEvent<HTMLInputElement>, value: string) => {
    setIsChecked(!isChecked);
    checkedItemHandler(value, e.target.checked);

    console.log(value, e.target.checked);
  };

  const onSubmit = useCallback(
    (e: React.FormEvent<HTMLFormElement>) => {
      e.preventDefault();

      console.log('checkedList:', checkedList);
    },
    [checkedList]
  );
  return (
    <div>
      <h1>Fruits list</h1>

      <form onSubmit={onSubmit}>
        <div className='checkbox-group'>
          {checkBoxList.map((item, idx) => (
            <div className='checkbox' key={idx}>
              <input
                type='checkbox'
                id={item}
                checked={checkedList.includes(item)}
                onChange={(e) => checkHandler(e, item)}
              />
              <label htmlFor={item}>{item}</label>
            </div>
          ))}
        </div>

        <button type='submit'>submit</button>
      </form>
    </div>
  );
};

export default CheckBoxes;

영상으로 확인하기

 

 

콘솔 로그 값 확인하기