概要
use-media
ライブラリを使って、レスポンシブ対応してみます。
各デバイスのサイズに対応するBoolean値(isMobileSite, isTabletSite, isPcSite)を定義してContextを使いアプリケーション全体で共有します。共有されたBoolean値を参照し、各デバイス毎に用意したコンポーネントを出し分けすることでレスポンシブ対応を行います。
環境
- react v17.0.2
- use-media v1.4.0
- typescript v4.1.2
インストール
# npmでのインストール
$ npm install --save use-media
# yarnでのインストール
$ yarn add use-media
実装
MediaQueryProvider
下記役割のコンポーネント、カスタムフックを定義してexportします。
- デバイスのサイズに対応するBoolean値をContextでアプリケーション全体に共有するための
MediaQueryProvider
- Providerコンポーネントから共有されたBoolean値を取得するカスタムフック
useMediaQueryContext
各デバイスのブレイクポイントはhttps://hashimotosan.hatenablog.jp/entry/2020/12/06/182327を参考にしました。
Components/Provider/MediaQueryProvider.tsx
import React, { createContext, FC, useContext, useMemo } from 'react';
import useMedia from 'use-media';
type Props = {
children: React.ReactNode;
};
// アプリケーション全体で共有する値の定義
type Context = {
// モバイルか?
isMobileSite: boolean;
// タブレットか?
isTabletSite: boolean;
// PCか?
isPcSite: boolean;
};
// Contextの生成
// デフォルトはPCとする。
const MediaQueryContext = createContext<Context>({
isMobileSite: false,
isTabletSite: false,
isPcSite: true,
});
// 各デバイスでのサイズを定義
const mediaQueries = {
mobile: '(max-width: 519px)',
tablet: '(min-width: 520px) and (max-width: 959px)',
pc: '(min-width: 960px)',
};
export const MediaQueryProvider: FC<Props> = ({ children }: Props) => {
const isMobileSite = useMedia(mediaQueries.mobile);
const isTabletSite = useMedia(mediaQueries.tablet);
const isPcSite = useMedia(mediaQueries.pc);
const value = useMemo(() => ({ isMobileSite, isTabletSite, isPcSite }), [
isMobileSite,
isTabletSite,
isPcSite,
]);
return (
<MediaQueryContext.Provider value={value}>
{children}
</MediaQueryContext.Provider>
);
};
export const useMediaQueryContext = (): Context =>
useContext(MediaQueryContext);
App
MediaQueryProviderがメインのコンポーネントを囲うようにします
App.tsx
import React from 'react';
import MainComponent from 'components/pages/MainComponent';
import { MediaQueryProvider } from 'components/provider/MediaQueryProvider';
export default function App() {
return (
<MediaQueryProvider>
<MainComponent />
</MediaQueryProvider>
);
}
MainComponent
useMediaQueryContext
を使用し、全体に共有されたBoolean値を取得し、Trueの場合に対応するコンポーネントを出力するようにします。
components/pages/MainComponent
import React, { FC } from 'react';
import MobileContents from 'components/templates/MobileContents';
import TabletContents from 'components/templates/TabletContents';
import PcContents from 'components/templates/PcContents';
import { useMediaQueryContext } from 'components/provider/MediaQueryProvider';
const MainComponent: FC = () => {
const { isMobileSite, isTabletSite, isPcSite } = useMediaQueryContext();
return (
{isMobileSite && (
<MobileContents />
)}
{isTabletSite && (
<TabletContents />
)}
{isPcSite && (
<PcContents />
)}
);
};
export default MainComponent;
まとめ
今回はReactでレスポンシブ対応を実装するuseMedia
を使ってみました。
各デバイスに対応するコンポーネントを作成することで、簡単にレスポンシブ対応が可能になります。
今後も試してみたライブラリなどを共有していきます。