ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 리액트에서 다수의 체크 박스 다루기
    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;
    

    영상으로 확인하기

     

     

    콘솔 로그 값 확인하기

     

    댓글

Designed by Tistory.