[TIL][Intern] React hooks - Resize event Listener

이나현·2021년 9월 22일
0

React

목록 보기
8/10

브리딩 홈페이지 리뉴얼 작업을 하던 중, 페이지의 너비에 따라 slider 버튼이 생기고 지워지는 기능을 추가해야했다.

기획/디자인


media query 말고 resize 이벤트를 쓴 이유

media query 말고 resize 이벤트를 쓴 이유는 크게 두가지이다.

1) media query로 동일한 기능을 각각 구현해야한다는 점=> 똑같은 display: none을 3번을 써야한다는 게 불편하다고 생각했다.

2) resize 이벤트는 해당 버튼 뿐만 아니라 모바일에만 나타야하는 컴포넌트에서 미디어쿼리로 나타나게 되어position: absolute로 일어나는 css 문제에 대한 해결책이 되기 때문

Resize event

  • 뷰포트가 960미만일 때, slider 기능을 할 수 있는 버튼 생성 이벤트 필요

첫번째 시도

뷰포트가 960 미만일 때를 구해야하기 때문에 처음에는 window.innerWidth를 사용해서 만드려고 했다.

const [WIDTH, setWIDTH] = useState(window.innerWidth);
.
.
.
{WIDTH <960 ? (<button></buttom>) : null} 

이렇게 하면 렌더링의 문제로 늦게 버튼이 나오는 걸 확인할 수 있었다! 그래서 찾아본 다른 솔루션

React Hooks - Resize Event

자바스크립트로 resize event를 만드려면 다음과 같다.

object.addEventListener("resize",myScript);
  • object : window
  • myScript: function(){~}

react로도 resize 이벤트를 만들 수 있지 않을까해서 찾아낸 해결책이 있다.

//useResize.jsx
import {useState, useEffect} from 'react';

const getWidth = () => window.innerWidth //뷰포트의 폭 가져오기 
|| document.documentElement.clientWidth //content만의 너비
|| document.body.clientWidth;

function useCurrentWidth() {
  //default는 위의 getWidth()
  let [WIDTH, setWIDTH] = useState(getWidth());

  //useEffect로 한번만 렌더링될 수 있게 만듦
  useEffect(() => {
  
  //timeoutId for debounce mechanism
  let timeoutId = null;
  
  const resizeListener = () => {
    // setTimeout을 취소
    clearTimeout(timeoutId);
    
    // WIDTH의 변화를 150 miliseconds 뒤에 변화시킴
    timeoutId = setTimeout(() =>setWIDTH(getWidth()),150)
  };
  window.addEventListener('resize', resizeListener);
  
  //clean up function 
  return () => {
    window.removeEventListener('resize', resizeListener)
  }
  }, [])
  
  return WIDTH;
}

debounce? 자주 사용되는 이벤트나 함수들의 실행 빈도를 줄여서 성능의 유리함을 가져오기 위한 개념이다. debounce는 입력 주기가 끝나면 출력한다.

이렇게 해서 React Hook을 만들고! 아래와 같이 썼다!

//resize event
const WIDTH = useResize();
.
.
.
{WIDTH > 960 ? null : (<button className={cx("vidoeBtn")} onClick={handleNextBtn}></button>)}
profile
technology blog

0개의 댓글