debounce로 화면 크기에 따라 컴포넌트 다르게 렌더링하기

cordelia·2021년 8월 7일
0

Why & When?

화면 크기에 따라 컴포넌트를 다르게 렌더링하고 싶을 때,

  1. resize 이벤트 이용해서 화면 크기를 state로 저장해야 하는 건 알겠는데,
  2. 매번 resize 이벤트 호출하면 낭비가 아닌가?에서 시작
  3. debounce 발견!

예시

화면 크기에 따라서 다른 텍스트를 보여주는 버튼을 만들 때

  • width > 768px일 경우
  • 그 외

작성한 코드

1. 화면 크기를 담는 state를 설정한다.

  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

window : 현재 스크립트가 작동 중인 창
window.innerWidth : 브라우저 윈도우의 뷰포트 너비로, 수직 스크롤바가 존재한다면 포함

2. useEffect로 resize 이벤트가 있으면 변경된 화면 크기를 state에 저장하는 함수를 호출하도록 한다.

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

resize 이벤트는 document view의 크기가 변경될 때 발생

useEffect훅에서 함수를 반환하면 컴포넌트가 unmount될 때 clean-up 함수가 실행된다. useEffect에 빈 배열을 전달하면, 컴포넌트가 처음 mount될 때와 unmount될 때 실행되는데, 컴포넌트가 unmount될 때 이벤트 리스너를 삭제하지 않으면 컴포넌트가 자주 리렌더링될 경우 메모리 누수가 발생하므로 리스너를 삭제하도록 한다.

3. debounce를 이용해서 resize 이벤트가 일어날 때마다 state를 변경하는 것이 아니라 마지막 resize 이벤트가 실행되고 1초가 지나면 그때서야 state를 변경하도록 한다(딱 한번!).

  const handleResize = debounce(() => {
    setWindowSize({
      width: window.innerWidth,
      height: window.innerHeight,
    });
  }, 1000);

Debounce : 동일 이벤트가 반복적으로 시행되는 경우 마지막 이벤트가 실행되고 나서 일정 시간 동안 해당 이벤트가 다시 실행되지 않으면 그때서야 해당 이벤트의 콜백 함수를 한번만 실행

4. 화면 크기(state)에 따라 보여줄 텍스트를 다르게 리턴


  return (
          <StyledButton type="primary" ghost onClick={showModal}>
            {windowSize.width > 768 ? '+ Add a Card' : '+ New'}
          </StyledButton>
        )
profile
There is so much scope for imagination in programming!

0개의 댓글