Skip to content
38

useMediaQuery

Live match for any CSS media query, like a breakpoint, dark mode or a touch screen. Renders a fixed value on the server so hydration never mismatches, then follows the real match.

Example

Installation

npx shadcn@latest add https://hirael.com/r/use-media-query.json

Usage

import { useMediaQuery } from "@/hooks/use-media-query"

Paths assume the default @/ alias from your components.json.

API

useMediaQuery()

ParameterTypeDefault
query*stringnone
serverValuebooleanfalse
Returnsboolean

Source

import * as React from 'react';

/**
 * Live match for a CSS media query, like `(min-width: 768px)`. The server and
 * hydration render read `serverValue`, so markup never mismatches; the real
 * match takes over right after.
 */
export const useMediaQuery = (query: string, serverValue = false) => {
  const subscribe = React.useCallback(
    (onStoreChange: () => void) => {
      const list = window.matchMedia(query);
      list.addEventListener('change', onStoreChange);

      return () => list.removeEventListener('change', onStoreChange);
    },
    [query],
  );

  return React.useSyncExternalStore(
    subscribe,
    () => window.matchMedia(query).matches,
    () => serverValue,
  );
};

Shipped