react
의 핵심 요소 중 하나는 훅(hook)이라고 할 수 있다. 보통 처음 react
를 배울 때 투두리스트 또는 숫자 카운터를 만들어 보며 개념을 익히는데, useState
를 사용하여 상태를 관리하고 useEffect
를 사용해 바뀐 상태를 렌더링 하는 법을 제일 먼저 배우는 것 같다.
react
에서는 이 훅(hook)을 직접 커스텀하여 사용할 수가 있다. 애플리케이션 전역에서 사용되는 상태에 따라 관리되어야 하는 함수를 이용하면 편리하게 아무 컴포넌트에서나 import하여 사용할 수 있다.
아래는 예시로 만든 코드이다. react
애플리케이션을 반응형으로 제작하기 위해서는 javascript
에 내장되어 있는 window 객체에 접근하여 브라우저의 너비와 높이를 가져오는데 아래와 같이 커스텀 훅을 생성하여 사용하면, 브라우저의 사이즈를 사용자가 변경할 때마다 상태를 업데이트하여 해당 훅을 사용하는 컴포넌트로 데이터를 뿌려준다.
커스텀 훅을 만들 때는 해당 파일과 함수의 이름을 use... 의 형태로 만들어야 한다.
import { useState, useEffect } from 'react';
import { debounce } from 'lodash';
import { ComponentSize } from '../types/common/ComponentSizeInterface';
function useDocumentSize(): ComponentSize {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
// handleResize 함수를 debounce로 감싸고, 시간을 설정한다
const handleResize = debounce(() => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight
});
}, 1000);
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => { // cleanup
window.removeEventListener('resize', handleResize);
}
}, []);
return windowSize;
}
export default useDocumentSize;
참고로 여기서 사용한
lodash
라이브러리는 일반적으로array
,collection
,date
등 데이터의 필수적인 구조를 쉽게 다루기 위해 널리 사용되는javascript
라이브러리이다. 여기서는debounce
함수를 사용하였는데 이 함수는 복적인 특정 동작을 반복되는 과정에서 강제적으로 대기하도록 한다.
handleResize
함수가 너무 빠르게 호출되어 부하가 높아지는 것을 방지하기위해 1초동안 강제로 대기하도록 하였다.
그리고 App.tsx
에서 아래 코드를 추가하여 window의 너비가 변경될 때마다 화면 너비가 정해진 MOBILE_SIZE
보다 작은지를 판단하여 redux
에 isMobile
상태를 dispatch 하여 애플리케이션 전역에서 같은 isMobile
상태값을 공유하도록 하였다.
const dispatch = useDispatch();
const isMobile = useSelector((state: RootStateInterface) => state.platform.isMobile);
useEffect(() => {
dispatch(setIsMobile({ isMobile: windowWidth < MOBILE_SIZE }))
}, [windowWidth])