모바일과 데스크탑을 구분하는 React 커스텀 Hook
FE/React2024. 8. 27. 18:18반응형 웹을 구현할 때, 모바일과 데스크탑 환경을 구분해야 할 때가 종종 있습니다. 본 글에서는 React에서 모바일 환경인지 데스크탑 환경인지 구분하는 훅(hook
)을 만드는 방법에 대해 소개합니다.
모바일과 데스크탑 환경을 왜 구분해야 하는가?
여러가지 이유가 있겠지만, 저의 경우 CSS의 hover
때문에 구분이 필요했습니다.
모바일 환경에서는 터치를 시작(touch start
)했거나 터치를 하는 중(touch
)이거나 터치를 끝냈거나(touche end
)와 같이 3가지 상태를 가지게 됩니다. 데스크탑 환경에서와 같이 hover가 존재하지 않기 때문에, 모바일에서는 hover 값이 정상적으로 먹히지 않습니다. 따라서 저는 구분을 위해 커스텀 훅을 만들어서 사용합니다.
구현 방법
CSS 미디어 쿼리를 이용하여 모바일과 데스크탑을 구분하여 스타일링을 할 수도 있으나, 본 글에서는 react 프로젝트에서 사용하는 방식에 대해 소개하고 있으므로 React의 커스텀 훅을 만들어서 구분하는 방법에 대해 설명하겠습니다.
커스텀 훅 구현
모바일 환경인지 구분할 수 있는 state를 만들겠습니다.
export const useIsMobile = () => {
const [isMobile, setIsMobile] = useState<boolean>(false);
return isMobile;
}
그리고, 현재 브라우저가 모바일 환경인지 확인하는 메소드를 구현하고, useEffect
에서 isMobile
의 변수를 설정해줍니다.
export const useIsMobile = () => {
const [isMobile, setIsMobile] = useState<boolean>(false);
useEffect(() => {
const checkIsMobile = () => {
const userAgent = typeof window.navigator === 'undefined' ? '' : navigator.userAgent;
const mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
userAgent,
);
setIsMobile(mobile || ('ontouchstart' in window && window.innerWidth <= 1024));
};
checkIsMobile();
}, []);
return isMobile;
};
마지막으로, 윈도우 사이즈가 줄었을때 모바일 환경으로 변경되었을 수도 있으므로, resize 이벤트를 추가합니다. 여기서 낭비되는 리소스를 방지하기 위해 clean-up
함수에 이벤트 리스너를 제거하는 로직도 같이 추가합니다.
export const useIsMobile = () => {
const [isMobile, setIsMobile] = useState<boolean>(false);
useEffect(() => {
const checkIsMobile = () => {
const userAgent = typeof window.navigator === 'undefined' ? '' : navigator.userAgent;
const mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
userAgent,
);
setIsMobile(mobile || ('ontouchstart' in window && window.innerWidth <= 1024));
};
checkIsMobile();
window.addEventListener('resize', checkIsMobile);
return () => window.removeEventListener('resize', checkIsMobile);
}, []);
return isMobile;
};
useIsMobile() 훅 사용 예시
커스텀 훅을 만들었으니 실제로 사용해봅시다. 저는 보통 tailwindcss
를 많이 사용하기 때문에 tailwindcss와 같이 사용하는 예시를 들도록 하겠습니다.
IconButton
컴포넌트를 하나 만들었습니다. 여기서 hover(클릭을 하기 위해 마우스를 올렸을때) 상태일때 스타일은 모바일에서 먹히지 않으므로, useIsMobile()
커스텀 훅으로 구분하여 분기처리를 하였습니다.
import { ReactNode } from 'react';
import classNames from 'classnames';
import { useIsMobile } from '@/hooks';
function IconButton({ icon, onClick }: { icon: ReactNode; onClick: () => void }) {
const isMobile = useIsMobile();
return (
<button
className={classNames(
'cursor-pointer rounded-full flex items-center justify-center w-[40px] h-[40px] sm:w-[50px] sm:h-[50px] text-indigo-500 transition ease-in-out duration-150 active:bg-indigo-700 active:text-white',
isMobile ? '' : 'hover:text-white hover:bg-indigo-500', // 모바일 환경의 경우는 hover를 제거
)}
onClick={onClick}
>
{icon}
</button>
);
}
'FE > React' 카테고리의 다른 글
간단한 React To Do 앱을 만들어보자 (2) | 2024.09.03 |
---|---|
useMemo를 사용하면 정말로 성능이 좋아질까? (0) | 2024.08.28 |
Vite기반 React 프로젝트에서 Path Aliasing 설정하기 (0) | 2024.08.26 |
Vite 기반 React 프로젝트에 Tailwind CSS 적용하기 (0) | 2024.08.25 |
Bun 설치 및 React 프로젝트 생성하기 (0) | 2024.08.24 |
IT 기술에 대한 글을 주로 작성하고, 일상 내용, 맛집/숙박/제품 리뷰 등 여러가지 주제를작성하는 블로그입니다. 티스토리 커스텀 스킨도 개발하고 있으니 관심있으신분은 Berry Skin을 검색바랍니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!