TIL32, React: 모달창 버그픽스!

sunghoonKim·2021년 1월 1일
2

useEffect 를 조금 더 깨달았다.


버그

공통으로 사용될 모달창을 클래스형으로 구현해 두었었다. 그것을 훅스로 재코딩했는데, 아래 코드와 같다.

const PopUp = ({ title, handleExit, children, bottom }) => {
  const popUpRef = useRef();
  const backgroundRef = useRef();

  useEffect(() => {
    console.log("이펙트가 일어났다");
    document.body.style.overflow = "hidden";
    backgroundRef.current.addEventListener("mousedown", handleClickOutside);
  });

  const handleClickOutside = event => {
    event.stopPropagation();
    console.log(event.target);
    if (popUpRef.current === null || !popUpRef.current.contains(event.target)) {
      document.body.style.overflow = "unset";
      handleExit();
    }
  };
 
  return (...);
}

팝업창이 띄워지면서, 배경부분에 이벤트 리스너를 붙여준다. 이후 해당 이벤트 리스너를 통해 바깥부분을 클릭할 시 팝업창이 꺼지는 구조다.

잘 만들었다 생각했고, 리뷰도 통과하여 머지까지 순조롭게 됐지만, 같은 팀원분께서 사용하시면서 예상치 못했던 버그를 발견하셨다.

팝업창내 컨텐츠가 스테이트 변화가 생겨 새로 렌더링이 될때마다, 이벤트 리스너가 계속 붙여지고 결국, 한번의 클릭을 수백개의 이벤트 리스너가 감지하는 불상사가 벌어졌다.


입력할때마다 거침없이 올라가는 이벤트 리스너의 숫자가 보인다. 이후엔, 한번만 클릭해도 이벤트 리스너의 숫자 갯수대로 이벤트를 감지한다. 이벤트 폭탄 완성.


픽스

는 생각보다 너무 간단하다.

useEffect 에서 2번째 인자로 아무것도 넘겨주지 않았기 때문에, 모든 업데이트에 대해서 useEffect 가 발생한다. 클래스형으로 치면, componentDidUpdate 부분에 이벤트 리스너 생성을 달아둔 셈.

따라서 두번째 인자로 [] 빈 배열을 넘겨준다. 이렇게 된다면, useEffectcomponentDidMount 의 역할을 하게된다. 팝업창이 띄어지고 최초 한번만 이벤트 리스너를 생성한다.

VSC 에서는 밑줄을 그어 무언가 잘못되었다고 표시한다.

무시한다.


결과

ㅗㅜㅗㅜ 너무 잘되고.


빨리 팀원분께 이 기쁜 소식을 알려드리러 가야지.

0개의 댓글