ReactのuseMediaQueryフックで画面サイズを感知して、ダイナミックなWebデザインを実現
React でビューポートサイズに基づいて条件付きレンダリングを行う方法
メディアクエリフックを使用する
最も簡単で一般的な方法は、useMediaQuery
フックを使用することです。このフックは、指定されたメディアクエリが現在のビューポートサイズに一致するかどうかを判定し、その結果に基づいて値を返します。
import React, { useState, useMediaQuery } from 'react';
function MyComponent() {
const isSmallScreen = useMediaQuery('(max-width: 768px)');
if (isSmallScreen) {
return <MobileComponent />;
} else {
return <DesktopComponent />;
}
}
この例では、useMediaQuery
を使用して、画面幅が768px以下の場合に MobileComponent
を、それ以外の場合は DesktopComponent
をレンダリングします。
window.matchMedia API を使用する
window.matchMedia
API を使用して、メディアクエリの変化を監視し、それに応じてコンポーネントを更新することもできます。
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [isSmallScreen, setIsSmallScreen] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia('(max-width: 768px)');
mediaQuery.addEventListener('change', (event) => {
setIsSmallScreen(event.matches);
});
return () => mediaQuery.removeEventListener('change');
}, []);
if (isSmallScreen) {
return <MobileComponent />;
} else {
return <DesktopComponent />;
}
}
この例では、useEffect
フックを使用して window.matchMedia
API にリスナーを追加し、メディアクエリの変化を検出しています。メディアクエリが一致すると、isSmallScreen
ステートが更新され、コンポーネントが再レンダリングされます。
サードパーティライブラリを使用する
react-responsive
や react-media
などのサードパーティライブラリを使用して、ビューポートサイズに基づいてコンポーネントをレンダリングすることもできます。これらのライブラリは、より多くの機能と柔軟性を提供することがありますが、設定と使用が複雑になる場合があります。
- アクセシビリティ
すべてのユーザーがコンテンツにアクセスできるように、ビューポートサイズに基づいてコンテンツを非表示にすることは避けてください。代わりに、異なるビューポートサイズに合わせてコンテンツを調整することを検討してください。 - パフォーマンス
ビューポートサイズの変化に応じて頻繁にコンポーネントをレンダリングすると、パフォーマンスが低下する可能性があります。パフォーマンスを向上させるために、useMemo
やshouldComponentUpdate
などの React のパフォーマンス最適化テクニックを使用することを検討してください。
import React from 'react';
import MobileComponent from './MobileComponent';
import DesktopComponent from './DesktopComponent';
function App() {
const isSmallScreen = useMediaQuery('(max-width: 768px)');
if (isSmallScreen) {
return <MobileComponent />;
} else {
return <DesktopComponent />;
}
}
export default App;
MobileComponent.js
import React from 'react';
function MobileComponent() {
return (
<div>
<h1>モバイル用のコンポーネント</h1>
<p>このコンポーネントは、画面幅が768px以下の場合に表示されます。</p>
</div>
);
}
export default MobileComponent;
DesktopComponent.js
import React from 'react';
function DesktopComponent() {
return (
<div>
<h1>デスクトップ用のコンポーネント</h1>
<p>このコンポーネントは、画面幅が768pxを超える場合に表示されます。</p>
</div>
);
}
export default DesktopComponent;
このコードを実行すると、画面幅が768px以下の場合は MobileComponent
が、それ以外の場合は DesktopComponent
が表示されます。
上記以外にも、window.matchMedia
API やサードパーティライブラリを使用してビューポートサイズに基づいてコンポーネントをレンダリングする方法はたくさんあります。
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [isSmallScreen, setIsSmallScreen] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia('(max-width: 768px)');
mediaQuery.addEventListener('change', (event) => {
setIsSmallScreen(event.matches);
});
return () => mediaQuery.removeEventListener('change');
}, []);
if (isSmallScreen) {
return <MobileComponent />;
} else {
return <DesktopComponent />;
}
}
- react-responsive ライブラリを使用するサンプル
import React from 'react';
import { Responsive } from 'react-responsive';
function MyComponent() {
return (
<div>
<Responsive xs={6} md={12}>
<MobileComponent />
</Responsive>
<Responsive md={12}>
<DesktopComponent />
</Responsive>
</div>
);
}
これらのサンプルは、ビューポートサイズに基づいてコンポーネントをレンダリングするための様々な方法を示すほんの一例です。
注意事項
npm install react react-media-query
カスタムフックを使用して、useMediaQuery
フックなどのロジックをカプセル化することができます。これにより、コードをより整理し、再利用しやすくなります。
import React, { useState, useEffect } from 'react';
function useViewportSize() {
const [isSmallScreen, setIsSmallScreen] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia('(max-width: 768px)');
mediaQuery.addEventListener('change', (event) => {
setIsSmallScreen(event.matches);
});
return () => mediaQuery.removeEventListener('change');
}, []);
return isSmallScreen;
}
function MyComponent() {
const isSmallScreen = useViewportSize();
if (isSmallScreen) {
return <MobileComponent />;
} else {
return <DesktopComponent />;
}
}
この例では、useViewportSize
カスタムフックを作成して、画面幅が768px以下の場合に true
を返し、それ以外の場合は false
を返します。MyComponent
コンポーネントは、このフックを使用して、レンダリングするコンポーネントを決定します。
レンダリングコンポーネントを使用する
react-router
や react-redux
などのライブラリには、レンダリングコンポーネントと呼ばれる機能が含まれている場合があります。レンダリングコンポーネントを使用すると、特定の条件が満たされた場合にのみコンポーネントをレンダリングすることができます。
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import MobileComponent from './MobileComponent';
import DesktopComponent from './DesktopComponent';
function App() {
return (
<Switch>
<Route path="/" render={() => (
<IsMobile>
<MobileComponent />
</IsMobile>
<DesktopComponent />
)} />
</Switch>
);
}
const IsMobile = ({ children }) => {
const isSmallScreen = useMediaQuery('(max-width: 768px)');
return isSmallScreen ? children : null;
};
この例では、IsMobile
コンポーネントを使用して、画面幅が768px以下の場合にのみ MobileComponent
をレンダリングします。
Higher-Order Component (HOC) を使用する
Higher-Order Component (HOC) を使用して、コンポーネントに条件付きレンダリングロジックをラップすることができます。
import React from 'react';
import withViewportSize from './withViewportSize';
const MobileComponent = () => (
<div>
<h1>モバイル用のコンポーネント</h1>
<p>このコンポーネントは、画面幅が768px以下の場合に表示されます。</p>
</div>
);
const DesktopComponent = () => (
<div>
<h1>デスクトップ用のコンポーネント</h1>
<p>このコンポーネントは、画面幅が768pxを超える場合に表示されます。</p>
</div>
);
const withViewportSize = (Component) => {
const isSmallScreen = useMediaQuery('(max-width: 768px)');
return (props) => (
isSmallScreen ? <MobileComponent {...props} /> : <DesktopComponent {...props} />
);
};
const App = () => (
<div>
<withViewportSize Component={MobileComponent} />
<withViewportSize Component={DesktopComponent} />
</div>
);
この例では、withViewportSize
HOC を作成して、コンポーネントに条件付きレンダリングロジックをラップします。App
コンポーネントは、この HOC を使用して MobileComponent
と DesktopComponent
をレンダリングします。
どの方法を選択すべきか
どの方法を選択するかは、アプリケーションの要件と好みによって異なります。
- **既存のライ
- コードをより整理したい場合は、カスタムフックを使用するのがおすすめです。
- シンプルさを重視する場合は、
useMediaQuery
フックを使用するのがおすすめです。
reactjs