My Boundary As Much As I Experienced

useEffect 내에서 eventListener 설정 시 동작하는 원리 본문

FrontEnd/React

useEffect 내에서 eventListener 설정 시 동작하는 원리

Bumang 2024. 2. 15. 12:43

오늘 만든 resize 이벤트가 끝나면 0.5초 이후 true값을 반환하는 useCatchResizeEnd 훅.

import { useEffect, useState } from 'react';

export const useCatchResizeEnded = () => {
  const [isEnded, setIsEnded] = useState(false);

  useEffect(() => {
    let resizeTimeout: NodeJS.Timeout;
    setIsEnded(false);

    const handleResize = () => {
      clearTimeout(resizeTimeout);
      resizeTimeout = setTimeout(() => {
        console.log('timeout이 멈췄습니다.');
        setIsEnded(true);
      }, 500);
    };

    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  return [isEnded];
};

 

 

useEffect내에 의존성 배열을 비워뒀다.

순간 의존성배열이 없으면 mount될 때 한 번 실행되니

resize이벤트가 계속 발생해도 캐치 못하는게 아닌지 고민했다.

 

그러나 첫 mount 때 addEventListener를 등록 한 번 하면, 계속 resize를 listening하고있는 상태는 유지된다.

그리고 unmount될 때 클린업 함수가 실행되서 resize 리스너를 제거한다.

 

오히려 의존성 배열에 어떠한 상태를 넣었는데 그게 계속 업데이트되면

업데이트 될 때마다 useEffect내의 클린업 함수를 실행하고 다시 이벤트 리스너를 재등록하게 되기 때문에,

한 번 이벤트 리스너를 등록해두고 페이지를 이탈하기 전까지 쭈욱 유지하고 싶으면

의존성 배열을 비워두는 것이 좋다.

 

결과적으로 0.5초 이후 값이 바뀌는 isEnded로 throttle 비슷한 효과를 내며 불필요한 렌더를 방지할수 있다.