useMediaQuery
A hook that tracks a CSS media query without tearing during hydration.
Resize the window to see these change.
Installation
Usage
Subscribes to a CSS media query and re-renders when it starts or stops matching.
import { useMediaQuery } from "@/hooks/use-media-query";
function Navigation() {
const isDesktop = useMediaQuery("(min-width: 768px)");
return isDesktop ? <Sidebar /> : <MobileDrawer />;
}Server rendering
The hook is built on useSyncExternalStore, which takes a separate server snapshot. On the server
and during the first client render it returns defaultValue, then switches to the real result — so
React never has to reconcile two different trees for the same commit.
const prefersReducedMotion = useMediaQuery("(prefers-reduced-motion: reduce)", {
defaultValue: true,
});Pick the defaultValue that matches the markup you render on the server. For layout queries that
usually means the mobile branch; for prefers-reduced-motion it usually means the safe one.
Prefer CSS where you can. A media query in CSS costs nothing and never mismatches. Reach for this hook when the breakpoint has to change what renders — a different component, a different DOM structure — not just how it looks.
Notes
- The query string is passed straight to
window.matchMedia, so any valid media query works. - Changing
queryresubscribes automatically. - Listeners are registered with
addEventListener, and are cleaned up on unmount.