본문 바로가기
개발/개발지식

[React] React 반응형 레이아웃 사용하기 + Typescript

by 그레이웅 2022. 12. 9. 16:57
반응형

 

 

React에서 미디어쿼리나 화면 사이즈에서 대해 바뀌는 화면을 구현하기 위해 react-responsive 라이브러리를 사용했다.

 

https://www.npmjs.com/package/react-responsive

 

react-responsive

Media queries in react for responsive design. Latest version: 9.0.2, last published: 10 days ago. Start using react-responsive in your project by running `npm i react-responsive`. There are 1036 other projects in the npm registry using react-responsive.

www.npmjs.com

 

설치 방법

npm install react-responsive --save

//typescript 
npm install @types/react-responsive --save

 

 

사용 방법

 

useMediaQuery를 import 해주고 아래 예제 처럼 화면 크기별로 분기를 해주고 해당 컴포넌트를 렌더링하게 해주었다.

//useMediaQuery를 import 해준다.
import { useMediaQuery } from "react-responsive";


//children을 받기 위한 타입 설정
type responsiveProps = {
  children : React.ReactNode
}

  const Desktop = ({ children }: responsiveProps) => {
    console.log(children);
    const isDesktop = useMediaQuery({ minWidth: 992 })
    return isDesktop ? <>{children}</> : null
  }
  const Tablet = ({ children }:responsiveProps) => {
    const isTablet = useMediaQuery({ minWidth: 768, maxWidth: 991 })
    return isTablet ? <>{children}</> : null
  }
  const Mobile = ({ children }:responsiveProps) => {
    const isMobile = useMediaQuery({ maxWidth: 767 })
    return isMobile ? <>{children}</> : null
  }
  const Default = ({ children }:responsiveProps) => {
    const isNotMobile = useMediaQuery({ minWidth: 768 })
    return isNotMobile ? <>{children}</> : null
  }
  
	return (
    <div className={styles.container}>
      //....
      <div>
        //해당하는 사이즈별로 컴포넌트가 보여지게된다.
        <Desktop>
          <div>Desktop or laptop</div>
        </Desktop>
        <Tablet>Tablet</Tablet>
        <Mobile>Mobile</Mobile>
        <Default>Not mobile (desktop or laptop or tablet)</Default>
      </div>
 </div>
  )
}

 

 

구현 화면

위 코드를 내 프로젝트의 적용해 본 결과이다.

 

 

추가

 

React Hydration Error

계속 Hydration 에러가 떠서 다음과 같이 코드를 수정하였다.

 

렌더링된 결과가 첫번째 렌더링 된 결과와 렌더된 React의 렌더트리의 차이가 있어서 에러가 발생하였다. 그래서 위에 설정한 컴포넌트의 하위 컴포넌트로 옮기고 코드를 다음과 같이 수정하였다.

 

에러내용

Error: Hydration failed because the initial UI does not match what was rendered on the server.

See more info here: https://nextjs.org/docs/messages/react-hydration-error

 

import React, {useEffect} from 'react';
import { product } from './productSlice';
import { useAppDispatch } from '../../app/hooks';

import { useMediaQuery } from "react-responsive";

// type responsiveProps = {
//   children : React.ReactNode
//  }

export function Product() {
   
    
    // const Desktop = ({children}:responsiveProps ) => {
    //     const isDesktop = useMediaQuery({minWidth : 992})
    //     return isDesktop ? <>{children}</> : null
    // }

    const isDesktop:boolean = useMediaQuery({ minWidth: 992 })
    const isTablet:boolean = useMediaQuery({ minWidth: 768, maxWidth: 991 })
    const isMobile:boolean = useMediaQuery({ maxWidth: 767 })
    const isNotMobile:boolean = useMediaQuery({ minWidth: 768 })
    const dispatch = useAppDispatch();

    useEffect(() => {
        dispatch(product());
    }, [])

    return (
        <div>
            {/* <Desktop>
                <div>Desktop or laptop</div>
            </Desktop> */}
            {isDesktop && <div>Desktop or laptop</div>}
            {isTablet && <div>Tablet</div>}
            {isMobile && <div>Mobile</div>}
            {isNotMobile && <div>Not mobile (desktop or laptop or tablet)</div>}
        </div>
    );
};

 

반응형

댓글