DOM
useMediaQuery
Tracks whether a CSS media query currently matches.
Demo
live · imported from hookli
- (min-width: 768px)
- false
- (orientation: landscape)
- false
- (prefers-color-scheme: dark)
- false
- (prefers-reduced-motion: reduce)
- false
Resize the window across 768px — the first row flips live as the query starts and stops matching.
import { useMediaQuery } from "hookli";
export function Demo() {
const isWide = useMediaQuery("(min-width: 768px)");
return <p>{isWide ? "Desktop layout" : "Mobile layout"}</p>;
}Usage
import { useMediaQuery } from "hookli";
export function Demo() {
const isWide = useMediaQuery("(min-width: 768px)");
return <p>{isWide ? "Desktop layout" : "Mobile layout"}</p>;
}API
useMediaQuery(query: string, options?: UseMediaQueryOptions): booleanParameters
| Name | Type | Default | Description |
|---|---|---|---|
| query | string | — | A CSS media query string, e.g. "(min-width: 768px)" or "(prefers-color-scheme: dark)". |
| options | UseMediaQueryOptions | {} | SSR default and hydration behaviour. Optional. |
Returns
| Name | Type | Description |
|---|---|---|
| matches | boolean | Whether the query currently matches. Re-renders on every matchMedia change event, and starts from defaultValue on the server. |
UseMediaQueryOptions
Configures the server value and mount behaviour.
| Name | Type | Description |
|---|---|---|
| defaultValue | boolean | Value returned on the server and before hydration. |
| initializeWithValue | boolean | Read the real match synchronously on mount. Set false to always start from defaultValue and avoid a hydration mismatch. |
Hook
The implementation, straight from hookli. Copy it, or install the package.
import { useState } from "react";
import { useIsomorphicLayoutEffect } from "../use-isomorphic-layout-effect/use-isomorphic-layout-effect";
interface UseMediaQueryOptions {
defaultValue?: boolean;
initializeWithValue?: boolean;
}
const IS_SERVER = typeof window === "undefined";
export function useMediaQuery(
query: string,
options: UseMediaQueryOptions = {},
): boolean {
const { defaultValue = false, initializeWithValue = true } = options;
const getMatches = (mediaQuery: string): boolean => {
if (IS_SERVER) return defaultValue;
return window.matchMedia(mediaQuery).matches;
};
const [matches, setMatches] = useState<boolean>(() => {
if (initializeWithValue) return getMatches(query);
return defaultValue;
});
useIsomorphicLayoutEffect(() => {
if (IS_SERVER) return;
const matchMedia = window.matchMedia(query);
const handleChange = () => setMatches(matchMedia.matches);
handleChange();
matchMedia.addEventListener("change", handleChange);
return () => {
matchMedia.removeEventListener("change", handleChange);
};
}, [query]);
return matches;
}