- media query를 사용해서 데스크톱 사이즈와 모바일 사이즈로 반응형 웹사이트를 만들었는데, 뼈대는 지정한 픽셀에 따라 바뀌었으나 메뉴는 props를 초반에 받아서 그리다보니까 새로고침을 해야 제대로 변경되었다.
- 이에 화면 사이즈가 변경되면 이를 감지하고, 자동으로 화면을 새로고침하는 로직을 넣으려고 한다. App component에서 window.outerWidth + useState를 사용해 상태로 만들고 useEffect를 활용하면 더 쉽고 간편하게 구현할 수도 있으나
많은 컴포넌트들에 모두 props로 내려줘야 할 것이기 때문에 상태관리 라이브러리를 설치 후에 그런 방법을 적용하려고 한다.
- 우선은 간단하게 window.addEventListner, window.removeEventListner를 사용해서 해당 기능을 구현했다.
//App.tsx
function App() {
const [windowSize, setWindowSize] = useState<number>(window.outerWidth); (1)
const handleResize = () => {setWindowSize(window.outerWidth);
}; (2)
useEffect(() => {
window.addEventListener('resize', handleResize); (3)
return () => {
window.removeEventListener('resize',handleResize) (4)
}
}, []); (5)
return (
<>
<div className='App'>{windowSize}
<Suspense fallback={<LoadingBunny />}>
<Routes>
<Route element={<BasicLayout />}>
<Route path={PATH.MAIN} element={<LandingPage />} />
{/* <Route path={PATH.CONTENTS} element={<Contents />} /> */}
</Route>
</Routes>
</Suspense>
</div>
</>
);
}
export default App;
- (1) : width에 따라 화면 변경을 감지 : window.outerWidth를 초기 state로 지정하고, 해당 값은 number type으로 설정해준다.
- (2) : handleResize 함수는 현재의 window.outerWidth를 받아서 windowSize 상태를 변경시키는 함수이다.
- (3), (4) : resize에 대한 이벤트는 window 객체에서 가능하다. 각각 'resize'에 대한 이벤트 리스너를 add/remove하고 이벤트가 발생했을 때 호출될 함수는 handleResize로 한다.
- (5) : 빈 배열을 종속성 배열로 넣으면 컴포넌트가 마운트/언마운트 될때만 렌더링한다. 이를 이용해 컴포넌트가 마운트될 때 리스너를 add하고 언마운트될 때 remove하게 한다.
2. debounce
- scroll, resize 등 이벤트 발생요청이 무수히 많아지면 성능 저하가 날 수 있다. 이를 방지하기 위해 debounce나 throttle 방법을 사용하는데 많은 이벤트를 그룹화했다가 동작이 끝나면 마지막 이벤트를 감지하는 debounce 기법을 사용해 성능 저하를 줄이려고 한다. 우선은 lodash 라이브러리를 이용해 구현한 후, 리팩토링시 clearTimeout, setTimeout을 이용하려고 한다.
//lodash(순수 JS로 작성된 유틸리티를 제공하는 라이브러리) 설치
npm i --save @types/lodash
//App.tsx
const handleResize = () => {
setWindowSize(window.outerWidth);
};
-> 많은 요청이 발생하는 부분을 debounce 콜백으로 처리하고, 시간은 1000ms로 지정한다.
const handleResize = debounce(() => {
setWindowSize(window.outerWidth);
}, 1000);