React Media Queries
react-media is a React component that enables declarative CSS media queries directly within React applications, simplifying responsive design. As of version 1.10.0, it offers a stable and widely used API for conditionally rendering components based on various viewport characteristics. While its release cadence is moderate rather than rapid, it has consistently received updates addressing compatibility with newer React versions and introducing key features like enhanced Server-Side Rendering (SSR) support via the `defaultMatches` prop and improved iframe integration with the `targetWindow` prop. It distinguishes itself by providing a clean, component-based abstraction over the native `window.matchMedia` API, allowing developers to focus on component logic rather than direct DOM API interaction.
Common errors
-
Warning: Accessing PropTypes via React.PropTypes is deprecated. Use the 'prop-types' package directly.
cause Using an older version of `react-media` (prior to 1.6.0) with a React version that has deprecated `React.PropTypes` (React 15.5 and above).fixUpdate `react-media` to version 1.6.0 or newer: `npm install react-media@latest` or `yarn add react-media@latest`. -
Warning: Prop `%s` did not match. Server: `%s` Client: `%s`
cause This hydration mismatch warning occurs during SSR because `react-media` cannot determine media query matches on the server without a `window` object, leading to a discrepancy between server-rendered and client-rendered HTML.fixProvide initial values for media queries on the server using the `defaultMatches` prop: `<Media queries={{ mobile: '(max-width: 768px)' }} defaultMatches={{ mobile: false }}>`. -
TypeError: Cannot read properties of undefined (reading 'matchMedia')
cause This error typically happens during Server-Side Rendering (SSR) when `react-media` attempts to access `window.matchMedia` in a server environment where `window` is undefined.fixEnsure you are either conditionally rendering `react-media` only on the client or, more commonly, provide `defaultMatches` for SSR scenarios as described in the hydration mismatch warning. Alternatively, implement a mock `window` object for server-side testing if necessary.
Warnings
- breaking Prior to v1.6.0, `react-media` used `React.PropTypes`. This was deprecated in React 15.5. Version 1.6.0 switched to the standalone `prop-types` package.
- gotcha When using `react-media` with Server-Side Rendering (SSR), the initial render on the server does not have access to the `window` object, leading to `matches` being `false` for all queries. This can cause hydration mismatches.
- gotcha For applications embedded within iframes, media queries are resolved against the parent window by default, which might not be the desired behavior.
Install
-
npm install react-media -
yarn add react-media -
pnpm add react-media
Imports
- Media
const Media = require('react-media'); // Incorrect for named export const Media = require('react-media').default; // react-media uses named exportsimport { Media } from 'react-media'; - useMedia
import { useMedia } from 'react-media'; - Media type
import type { MediaRenderProps } from 'react-media';
Quickstart
import React from 'react';
import { Media } from 'react-media';
interface MyResponsiveComponentProps {
children: React.ReactNode;
}
const MyResponsiveComponent: React.FC<MyResponsiveComponentProps> = ({ children }) => {
return (
<Media queries={{
small: '(max-width: 599px)',
medium: '(min-width: 600px) and (max-width: 1199px)',
large: '(min-width: 1200px)',
print: 'print'
}}>
{matches => (
<div style={{ padding: '20px', border: '1px solid #ccc' }}>
{matches.small && <p>You are on a small screen or mobile device.</p>}
{matches.medium && <p>You are on a tablet or medium-sized screen.</p>}
{matches.large && <p>You are on a desktop or large screen.</p>}
{matches.print && <p>Preparing for print!</p>}
{!matches.small && !matches.medium && !matches.large && !matches.print && (
<p>No specific media query matched (perhaps a server-side render without defaultMatches).</p>
)}
{children}
</div>
)}
</Media>
);
};
export default MyResponsiveComponent;