All hooks / Viewport and media
useMediaQuery
Tracks whether a CSS media query matches, and re-renders when it changes.
Renders serverValue on the server and during hydration, then switches to the real value with no hydration mismatch. Concurrent-safe: every component reads the same value in one render.
Import
import { useMediaQuery } from '@vincent.ri/react-tils'
// or only this hook
import { useMediaQuery } from '@vincent.ri/react-tils/useMediaQuery'Usage
const isWide = useMediaQuery('(min-width: 768px)')
const prefersDark = useMediaQuery('(prefers-color-scheme: dark)')
// Mobile-first site: assume narrow on the server.
const isDesktop = useMediaQuery('(min-width: 1024px)', false)Live demo
Resize the window, or switch your OS theme.
When to use it
JS logic depends on viewport size, prefers-color-scheme, prefers-reduced-motion, pointer type, or orientation.
When not to
Only styling changes. Use a CSS @media rule instead, which needs no JS and never flashes.
API
function useMediaQuery(query: string, serverValue?: boolean): boolean| Parameter | Description |
|---|---|
query | Any CSS media query, e.g. '(min-width: 768px)'. |
serverValue | Value on the server and during hydration. Pick the value most visitors will have, to minimize the switch after hydration. Default false. |
Browser support
| Uses | Chrome | Edge | Firefox | Safari | Chrome Android | Safari iOS |
|---|---|---|---|---|---|---|
| matchMediaWidely available | 9+ | 12+ | 6+ | 5.1+ | 18+ | 5+ |
First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).
Coming from another library?
Other libraries call this useMedia, useBreakpoint, useResponsive.