avatar

Le Do Nghiem

Software Engineer

  • About me
  • Books
  • Snippets
  • Blog

© 2026 Le Do Nghiem. All rights reserved.

Contact |

Back to Snippets

useMediaQuery Hook

React hook to track CSS media query matches for responsive design.

LanguageTypeScript
Last UpdatedMay 3, 2025
use-media-query.ts
import { useState, useEffect } from 'react';

export function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const media = window.matchMedia(query);
    
    // Set initial value
    if (media.matches !== matches) {
      setMatches(media.matches);
    }

    // Create listener
    const listener = (event: MediaQueryListEvent) => {
      setMatches(event.matches);
    };

    // Modern browsers
    if (media.addEventListener) {
      media.addEventListener('change', listener);
      return () => media.removeEventListener('change', listener);
    } else {
      // Fallback for older browsers
      media.addListener(listener);
      return () => media.removeListener(listener);
    }
  }, [matches, query]);

  return matches;
}

Media queries are essential for responsive design. This hook allows you to use media queries directly in React components, enabling conditional rendering based on screen size or other media features.

import { useState, useEffect } from 'react';

export function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const media = window.matchMedia(query);
    
    // Set initial value
    if (media.matches !== matches) {
      setMatches(media.matches);
    }

    // Create listener
    const listener = (event: MediaQueryListEvent) => {
      setMatches(event.matches);
    };

    // Modern browsers
    if (media.addEventListener) {
      media.addEventListener('change', listener);
      return () => media.removeEventListener('change', listener);
    } else {
      // Fallback for older browsers
      media.addListener(listener);
      return () => media.removeListener(listener);
    }
  }, [matches, query]);

  return matches;
}

How It Works

  • Uses window.matchMedia to check if a media query matches.
  • Listens for changes and updates state accordingly.
  • Handles both modern and legacy browser APIs.
  • Returns a boolean indicating if the query currently matches.

Example Usage

function ResponsiveComponent() {
  const isMobile = useMediaQuery('(max-width: 768px)');
  const isTablet = useMediaQuery('(min-width: 769px) and (max-width: 1024px)');
  const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');

  return (
    <div>
      {isMobile && <MobileView />}
      {isTablet && <TabletView />}
      {prefersDark && <DarkModeStyles />}
    </div>
  );
}

Common Breakpoints

function useBreakpoints() {
  const isSm = useMediaQuery('(min-width: 640px)');
  const isMd = useMediaQuery('(min-width: 768px)');
  const isLg = useMediaQuery('(min-width: 1024px)');
  const isXl = useMediaQuery('(min-width: 1280px)');

  return { isSm, isMd, isLg, isXl };
}

Dark Mode Example

function ThemeAwareComponent() {
  const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
  
  return (
    <div className={prefersDark ? 'dark-theme' : 'light-theme'}>
      Content adapts to system theme
    </div>
  );
}

Use Cases

  • Conditional rendering based on screen size
  • Detecting dark mode preference
  • Showing/hiding features on mobile
  • Adjusting layout for print media
  • Responsive navigation menus

Notes

  • More performant than useWindowSize for simple breakpoint checks.
  • Works with any valid CSS media query.
  • Consider debouncing if you need to limit update frequency.
  • For SSR, the initial value will be false until hydration.

A powerful hook that brings CSS media queries into your React components, enabling true responsive behavior.

Previous Snippet

useFetch Hook

Next Snippet

useWindowSize Hook