[React + TypeScript] useResize 커스텀 훅 만들기

김방울·2022년 12월 20일
2

React

목록 보기
2/6

보통 미디어 쿼리를 통해 반응형 레이아웃을 만드는 편을 선호하지만, 개발하다 보면 아주 가끔 미디어 쿼리만으로는 한계가 있는 경우가 있습니다.🤔

특정 페이지만 반응형 레이아웃을 구현해내야 했던 작업이 있어서 구글을 참고하며 사용했던 custom hook을 기록해 보았습니다.

  • utils.ts
import { useEffect, useState } from 'react';

// FUNCTION 모바일 웹 resize 관련
export const useResize = () => {
  const [windowSize, setWindowSize] = useState<SizeType>({
    width: undefined,
    height: undefined,
  });

  const handleResize = () => {
    setWindowSize({
      width: window.innerWidth,
      height: window.innerHeight,
    });
  };

  useEffect(() => {
    window.addEventListener('resize', handleResize);
    handleResize();
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return windowSize;
};

useResize 에서 반환한 값을 통해 특정 페이지만 반응형 레이아웃을 구현하고자 useSetMobileMode 이라는 커스텀 훅을 추가적으로 만들었습니다.

  • mediaSize.ts
export default {
  mobileSize: 480,
  tabletSize: 768,  
  laptopSize: 1024,
};

media query point 변수들을 mediaSize 라는 객체로 따로 적어주었습니다.

// utils.ts
import mediaSize from 'src/styles/mediaSize';

...

export const useSetMobileMode = (size: SizeType, className: string) => {
  useEffect(() => {
    const htmlDOM = document.querySelector('html');

    if (size.width && size.width <= mediaSize.mobileSize) {
      htmlDOM?.classList.add(className);
    } else if (htmlDOM?.classList.contains(className)) {
      htmlDOM?.classList.remove(className);
    }
    return;
  }, [size, className]);
  return;
};

type SizeType = {
  width?: number;
  height?: number;
};

useResize 에서 반환된 window 객체의 값과 className이 될 값을 인자로 받아,
특정 width값 이하에서 html에 인자로 받은 className 을 추가해 주는 커스텀 훅을 만들었습니다.

저는 특정 페이지에서 html 태그의 className만 수정하면 되는 상황이었고, width 값이 480px 이하일 때만 대응이 필요했기 때문에 다음과 같이 코드를 짰으나
받는 인자 값들과 조건문 (size.width && size.width <= mediaSize.mobileSize) 을 더욱 확장성 있게 수정한다면 더 여러 상황에 범용적으로 쓸 수 있을 것 같습니다!😀

만든 hook들은 다음과 같이 사용하였습니다.

const Main: React.FC = () => {
  const size = useResize();
  useSetMobileMode(size, 'mb');

  useEffect(() => {
    console.log(`width: ${size.width}, height: ${size.height}`);
  }, [size.width, size.height]);


자바스크립트로만 적용했었던 hook을 타입스크립트 프로젝트에 적용하면서, 타입 지정과 에러 수정에 시간이 조금 걸렸습니다.. 😂😂 얼른 타입스크립트랑 친해지고 싶네요😏

profile
코딩하는 고양이🐱 / UI Developer, Front-end Developer

0개의 댓글