useMediaQuery


Custom hook that tracks the state of a media query using the Match Media API.

Usage

import { useMediaQuery } from 'usehooks-ts'

export default function Component() {
  const matches = useMediaQuery('(min-width: 768px)')

  return (
    <div>
      {`The view port is ${matches ? 'at least' : 'less than'} 768 pixels wide`}
    </div>
  )
}

API

useMediaQuery(query, options?): boolean

Custom hook that tracks the state of a media query using the Match Media API.

Parameters

NameTypeDescription
querystringThe media query to track.
options?UseMediaQueryOptionsThe options for customizing the behavior of the hook (optional).

Returns

boolean

The current state of the media query (true if the query matches, false otherwise).

Type aliases

Ƭ UseMediaQueryOptions: Object

Hook options.

Type declaration

NameTypeDescription
defaultValue?booleanThe default value to return if the hook is being run on the server. Default ts false
initializeWithValue?booleanIf true (default), the hook will initialize reading the media query. In SSR, you should set it to false, returning options.defaultValue or false initially. Default ts true

Hook

import { useState } from 'react'

import { useIsomorphicLayoutEffect } from 'usehooks-ts'

type UseMediaQueryOptions = {
  defaultValue?: boolean
  initializeWithValue?: boolean
}

const IS_SERVER = typeof window === 'undefined'

export function useMediaQuery(
  query: string,
  {
    defaultValue = false,
    initializeWithValue = true,
  }: UseMediaQueryOptions = {},
): boolean {
  const getMatches = (query: string): boolean => {
    if (IS_SERVER) {
      return defaultValue
    }
    return window.matchMedia(query).matches
  }

  const [matches, setMatches] = useState<boolean>(() => {
    if (initializeWithValue) {
      return getMatches(query)
    }
    return defaultValue
  })

  // Handles the change event of the media query.
  function handleChange() {
    setMatches(getMatches(query))
  }

  useIsomorphicLayoutEffect(() => {
    const matchMedia = window.matchMedia(query)

    // Triggered at the first client-side load and if query changes
    handleChange()

    // Use deprecated `addListener` and `removeListener` to support Safari < 14 (#135)
    if (matchMedia.addListener) {
      matchMedia.addListener(handleChange)
    } else {
      matchMedia.addEventListener('change', handleChange)
    }

    return () => {
      if (matchMedia.removeListener) {
        matchMedia.removeListener(handleChange)
      } else {
        matchMedia.removeEventListener('change', handleChange)
      }
    }
  }, [query])

  return matches
}