티스토리 뷰

카테고리 없음

[북팡] 개별 선택, 전체 선택

개춘기뽀삐 2024. 11. 11. 20:40
// 개별 선택
export const onCheckedHandler = (
  e: ChangeEvent<HTMLInputElement>,
  item: any,
  setCheckItems: React.Dispatch<React.SetStateAction<any[]>>
) => {
  if (e.target.checked) {
    setCheckItems(prev => [...prev, item]);
  } else {
    setCheckItems(prev => prev.filter(check => check.id !== item.id));
  }
};

// 전체 선택 
export const allCheckedHandler = (
  e: ChangeEvent<HTMLInputElement>,
  data: any[],
  setCheckItems: React.Dispatch<React.SetStateAction<any[]>>
) => {
  if (e.target.checked) {
    setCheckItems(data);
  } else {
    setCheckItems([]);
  }
};
const SearchedData = () => {
  const [checkItems, setCheckItems] = useState<SearchTypes[]>([]);

  return (
    <div>
      <div>
        <input
          type="checkbox"
          onChange={e => allCheckedHandler(e, searchData, setCheckItems)}
          checked={checkItems.length === searchData.length}
          id="allChecked"
          className={styles["all-input"]}
        />
        <label htmlFor="allChecked">전체선택</label>

        <select name="" id="">
          <option value="">정확도순</option>
          <option value="">평점순</option>
          <option value="">후기순</option>
          <option value="">가격순</option>
          <option value="">판매량순</option>
          <option value="">출시일순</option>
          <option value="">상품명순</option>
        </select>
        {searchData?.map(item => {
          return (
            <div key={item.id}>
              <input
                type="checkbox"
                onChange={e => onCheckedHandler(e, item, setCheckItems)}
                checked={checkItems.some(check => check.id === item.id)}
              />
              <div>{item.title}</div>
              <div>{item.publisher}</div>
              <div>{item.author}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
};

 

개별선택

  • input 타입은 체크박스로 만든다
  • onCheck 이벤트가 아닌, onChange 이벤트를 사용한다
    • onCheck 클릭하는 순간 이벤트가 트리거 되기 때문에 상태가 변경되지 않아도 이벤트가 호출되지만 onChange는 상태 변화를 감지해 호출되기 때문
  • checked 속성은 체크박스와 라디오 버튼의 선택 상태를 반영하고 boolen값을 반환한다
  • 조건문으로 이벤트 대상 중(e.target)  체크된 데이터만 (checked: true) state 저장한다
  • 개별선택의 경우, 한 번에 여러 개를 선택하는 게 아닌 하나씩 선택이기 때문에 이전값에 새로운 값을 추가해줘야 한다
    • setCheckItems(prev => [...prev, item]);
    • prev 이전에 선택된 데이터 목록
    • item 현재 새로 선택한 데이터
    • [...prev, item] 기존 선택 목록에 새 데이터를 추가한 새로운 배열을 만들어서 setCheckItems에 저장
  • 선택 해제의 경우 state에 저장된 데이터와 (checked: false) 데이터를 비교, id가 같지 않은 것만 반환하면 체크된 데이터만 남게 된다  
    • setCheckItems(prev => prev.filter(selectedItem => selectedItem.id !== item.id));
    • prev는 현재 선택된 데이터 목록
    • filter 메서드는 선택된 데이터 중 해제할 데이터와 id가 일치하지 않는 항목만 남겨 새로운 배열을 만들어서 setCheckItems에 저장

 

전체 선택

  • 체크 상태를 확인하기 위해 input를 사용한다
  • lable을 이용해 input을 감싸 전체선택 텍스트만 클릭해도 input이 작동하도록 연결해 준다
    • 꼭 감싸지 않아도 label 태그에 htmlFor (for) 속성과 input id속성을 동일하게 해도 연결된다
  • checked 속성을 이용해 이벤트 대상이(e.target) 체크 상태이면 state에 데이터를 저장한다
  • 이벤트 대상이(e.target) 체크상태가 아닌 경우 state를 빈 배열로 만들어준다

 

*전체선택 시 버튼 대신 레이블을 사용한 이유

여러 페이지에서 사용하는 기능이라 공용 함수 파일에 분리해 재사용할 수 있도록 했다

전체선택 텍스트 옆에 체크박스가 노출되는 것과, 노출되지 않는 페이지가 있어서 체크박스가 보이지 않는 페이지는 display:none로 숨겨서 사용하면 되기 때문에 레이블로 통일했다


레이블로 인풋을 감싸지 않는 경우

       <input
          type="checkbox"
          onChange={e => allCheckedHandler(e, searchData, setCheckItems)}
          checked={checkItems.length === searchData.length}
          id="allChecked"
          className={styles["all-input"]}
        />
        <label htmlFor="allChecked">전체선택</label>
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함