Skip to content

React Integration

Import from responsive-media/react.

ts
import {
  useResponsive,
  useBreakpoints,
  useMediaQuery,
  useContainerState,
} from 'responsive-media/react'

useResponsive<T>()

Returns the current responsive state. Re-renders only when state changes. Uses useSyncExternalStore internally. Accepts a generic type parameter to narrow the returned state — see ConfigToState<T>.

tsx
import { useResponsive } from 'responsive-media/react'

type MyState = { sm: boolean; lg: boolean }

function App() {
  const { sm, lg } = useResponsive<MyState>()
  return sm ? <MobileNav /> : <DesktopNav />
}

useBreakpoints()

Returns ordered breakpoint helpers. Re-renders when the responsive state changes.

tsx
import { useBreakpoints } from 'responsive-media/react'

function Nav() {
  const { current, isAbove, isBelow, between } = useBreakpoints()
  return (
    <>
      <span>Current: {current}</span>
      {isAbove('sm') ? <DesktopNav /> : <MobileNav />}
      {between('sm', 'lg') && <TabletBanner />}
    </>
  )
}

Unlike Vue, current is a plain string | null (not a ref). Re-renders are triggered by useSyncExternalStore.

useMediaQuery(query)

boolean

Tracks a raw CSS media query string. SSR-safe (returns false on the server).

tsx
import { useMediaQuery } from 'responsive-media/react'

function ThemeToggle() {
  const isDark = useMediaQuery('(prefers-color-scheme: dark)')
  const canHover = useMediaQuery('(hover: hover)')
  return <button className={isDark ? 'dark' : 'light'}>Toggle</button>
}

useContainerState(ref, config, options?)

Tracks an element's dimensions and returns a state object. Sets up and tears down ResizeObserver via useEffect.

tsx
import { useRef } from 'react'
import { useContainerState } from 'responsive-media/react'

function Card() {
  const ref = useRef<HTMLDivElement>(null)
  const { compact, wide } = useContainerState(ref, {
    compact: [{ type: 'max-width', value: 300 }],
    wide: [{ type: 'min-width', value: 600 }],
  })

  return (
    <div ref={ref}>{compact ? <CompactLayout /> : wide ? <WideLayout /> : <DefaultLayout />}</div>
  )
}

config and options are treated as static after mount. Wrap in useMemo if they change.