[TIL] 내일배움캠프 React 과정 2024.06.28

김형빈·2024년 6월 28일
0

내일배움캠프

목록 보기
50/81
post-custom-banner

오늘의 한 일

  • 라이브 알고리즘 테스트
    • queue,stack 구현하기
  • 제일양심있주 ver.2
    • 모달창 로직 수정
    • 가격대 선택 체크박스 로직 수정

체크박스에서 1개만 선택가능하게 하기

기존의 로직

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  const checkboxes = document.getElementsByName('price') as NodeListOf<HTMLInputElement>;
  for (let i = 0; i < checkboxes.length; i++) {
    if (checkboxes[i] !== e.target) {
      checkboxes[i].checked = false;
    }
  }
};
  • 어제 타입 단언(assertion)을 활용하여 타입 오류를 잡아냈던 코드이다.
  • 물론 이렇게 해결해도 동작을 하지만 왜 타입 단언(assertion)을 하지 않으면 타입 오류가 발생하였던 걸까?
    • 정답은 document.getElementsByName 코드 때문!
    • 직접 DOM을 조작하는 함수를 다루는 것은 React에서 가상 DOM을 만들기 전이기 때문에 NodeListOf<HTMLInputElement>라는 것을 개발자가 알려주지 않으면 모르는 것이다.

Ref를 사용한 로직

const [priceRefs, setPriceRefs] = useState<React.RefObject<HTMLInputElement>[]>([]);
const priceFilterList = ['만원 이하', '1~2만원', '2~4만원', '4만원 이상'];

useEffect(() => {
  setPriceRefs(
    Array(4)
      .fill(0)
      .map(() => createRef())
  );
}, []);


const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  if (!priceRefs) return;
  for (let i = 0; i < priceRefs.length; i++) { 
    if (priceRefs[i].current !== null && priceRefs[i].current !== e.target) {
      priceRefs[i].current!.checked = false; 
    }
  }
};

...

return (
  		...
  		{priceFilterList.map((priceFilter, index) => (
            <Checkbox
              priceRef={priceRefs[index]}
              handler={handlePrice}
              handleChange={handleChange}
              value={priceFilter}
            />
          ))}
)
  • useRef 훅을 사용하여 checkBox input 태그의 checked 상태를 변경시킨다.

주의 사항!

다음의 방식대로 createRef를 사용할 경우 type 에러가 발생한다.

useEffect(() => {
  const initRefs = Array(4)
    .fill(0)
    .map(() => createRef());

  setPriceRefs(initRefs);
}, []);

변수에 생성된 createRef

useState에 생성된 createRef

  • createRef가 useState에 선언한 타입을 따라가기에 setState 함수 안에서 사용할 필요가 있다!

useState와 index를 활용하는 방법

const [checkedIndex, setCheckedIndex] = useState<number | null>(null);
const priceFilterList = ['만원 이하', '1~2만원', '2~4만원', '4만원 이상'];
const categoryFilterList = ['음식점', '미용업', '세탁업', '숙박업', '기타'];

const handleChange = (index: number) => {
    setCheckedIndex(index);
  };

...
return (
  ...
	  {priceFilterList.map((priceFilter, index) => (
            <Checkbox
              index={index}
              checked={checkedIndex === index}
              handler={handlePrice}
              handleChange={handleChange}
              value={priceFilter}
            />
          ))}
)
  • index를 활용하여 선택한 index와 checkbox의 index를 비교하여 checked의 상태를 바꾼다
  • 하지만 의도한데로 동작하지 않아 더 엄밀한 로직이 필요하다...
profile
The secret of getting ahead is getting started.
post-custom-banner

0개의 댓글