브리딩 홈페이지 리뉴얼 작업을 하던 중, 페이지의 너비에 따라 slider 버튼이 생기고 지워지는 기능을 추가해야했다.
media query 말고 resize 이벤트를 쓴 이유는 크게 두가지이다.
1) media query로 동일한 기능을 각각 구현해야한다는 점=> 똑같은 display: none
을 3번을 써야한다는 게 불편하다고 생각했다.
2) resize 이벤트는 해당 버튼 뿐만 아니라 모바일에만 나타야하는 컴포넌트에서 미디어쿼리로 나타나게 되어position: absolute
로 일어나는 css 문제에 대한 해결책이 되기 때문
- 뷰포트가 960미만일 때, slider 기능을 할 수 있는 버튼 생성 이벤트 필요
뷰포트가 960 미만일 때를 구해야하기 때문에 처음에는 window.innerWidth
를 사용해서 만드려고 했다.
const [WIDTH, setWIDTH] = useState(window.innerWidth);
.
.
.
{WIDTH <960 ? (<button></buttom>) : null}
이렇게 하면 렌더링의 문제로 늦게 버튼이 나오는 걸 확인할 수 있었다! 그래서 찾아본 다른 솔루션
자바스크립트로 resize event를 만드려면 다음과 같다.
object.addEventListener("resize",myScript);
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>)}