use-media

A tiny React hook that tracks live CSS media query state without manual matchMedia wiring.

Library
npm
v1.5.0
522stars
Unlicense

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
37/100Needs Attention
Development Activity0
Maintenance20
Community40
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
69/100Good
Architecture70
Code Quality55
Innovation65
Learning Curve85

use-media exposes a single useMedia hook that subscribes a React component to a CSS media query and re-renders it whenever the query’s match state changes. It accepts either a raw media query string or a plain object of media features (e.g. {minWidth: '1000px'}), which it converts to a query string internally, then wires up window.matchMedia and its change listener for you, cleaning the listener up on unmount.

The package also ships useMediaLayout, an identical hook built on useLayoutEffect for cases where you need the media state synchronously before paint. Because the whole implementation is a small wrapper around the native matchMedia API, it has zero runtime dependencies beyond React itself and is easy to reason about, mock in tests, or vendor if needed.

What You Get

  • A useMedia hook that returns a live boolean tracking whether a CSS media query currently matches
  • A useMediaLayout variant built on useLayoutEffect for synchronous, pre-paint reads of media state
  • Support for both raw query strings ('(min-width: 1000px)') and structured query objects ({minWidth: '1000px'})
  • Automatic conversion of camelCase feature keys to hyphenated CSS media feature names
  • A configurable defaultState argument for the initial render (useful for SSR)
  • An exported mockMediaQueryList plus TypeScript types for mocking matchMedia in Jest and other test runners

Common Use Cases

  • Conditionally rendering different layouts or components for mobile vs. desktop viewports
  • Reacting to prefers-reduced-motion or prefers-color-scheme to adjust animations or theming
  • Driving JS-side breakpoint logic that needs to stay in sync with CSS media queries
  • Sharing a small set of media query results across an app via React Context to avoid duplicate matchMedia listeners

Under The Hood

Architecture — The entire library is built around one factory function, createUseMedia(effect) in src/useMedia.ts, which is instantiated twice: once with useEffect to produce useMedia, and once with useLayoutEffect to produce useMediaLayout. Each call sets up local useState for the boolean match result, converts the passed query (string or object) via queryObjectToString, and inside the effect creates a MediaQueryList — either the real one from window.matchMedia(query) or a mockMediaQueryList stand-in when window is undefined (SSR safety) — attaches a change listener that updates state, seeds the initial state synchronously, and returns a cleanup function that detaches the listener and guards against post-unmount setState calls via a mounted flag.

Tech Stack — Pure TypeScript with react as the only peer dependency ("react": "*"); there are no runtime dependencies at all. The build step is a plain tsc compile to lib/, and releases are cut with semantic-release plus its changelog/npm/git plugins, visible in package.json’s release config and .travis.yml.

Code Quality — The codebase is very small (under 100 lines across src/) and cleanly decomposed: useMedia.ts holds the hook logic, utilities/queryObjectToString.ts and utilities/camelToHyphen.ts handle query-string conversion, and types.ts defines the shared Effect and MediaQueryObject types. There is no automated test suite — package.json’s test script is a placeholder (echo 'hmmmm....') — so correctness relies on the library’s small surface area and the exported mockMediaQueryList helper that downstream consumers use to test their own code against it.

API Design — The public API is deliberately minimal: import a hook, call it with a query, get a boolean back. Supporting both a raw CSS string and a structured object covers both power users who want exact media query syntax and casual users who’d rather write {minWidth: '1000px'}. The README documents SSR handling, Jest mocking, and a Context pattern for sharing queries across components, which lowers the barrier for the two trickiest real-world integration points (server rendering and testing).

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search