Implement a useMediaQuery
hook that subscribes and responds to media query changes (e.g. screen size, resolution, orientation, etc.).
export default function Component() {const isSmallDevice = useMediaQuery('only screen and (max-width: 768px)');return <div>{isSmallDevice && <a href="#">Menu</a>}</div>;}
Hint: The window.matchMedia
API would be helpful.
query: string
: The media query to match. It must be a valid CSS media query stringThe hook returns a boolean value that indicates whether the media query is a match.
Implement a useMediaQuery
hook that subscribes and responds to media query changes (e.g. screen size, resolution, orientation, etc.).
export default function Component() {const isSmallDevice = useMediaQuery('only screen and (max-width: 768px)');return <div>{isSmallDevice && <a href="#">Menu</a>}</div>;}
Hint: The window.matchMedia
API would be helpful.
query: string
: The media query to match. It must be a valid CSS media query stringThe hook returns a boolean value that indicates whether the media query is a match.
window.matchMedia(query)
is a JavaScript method that checks if the document matches a given CSS media query. It returns a MediaQueryList
object, which provides:
.matches
(boolean): Indicates whether the document currently matches the media query.addEventListener("change", callback)
: Listens for changes in the media query’s match state.removeEventListener("change", callback)
: Removes the event listener when it’s no longer neededExample:
const mediaQuery = window.matchMedia('(max-width: 768px)');if (mediaQuery.matches) {console.log('Viewport is 768px or smaller');}mediaQuery.addEventListener('change', (e) => {console.log(e.matches ? 'Now small screen' : 'Now large screen');});
useMediaQuery
is a hook that allows a React app to leverage this browser API and respond to media changes (e.g. screen size, resolution, orientation, and more).
useEffect
and useState
The useMediaQuery
hook can be implemented using the useState
hook to store the current media query match and the useEffect
hook to update the match when the media query changes. We can attach a listener to the change
event on the MediaQueryList
object returned by window.matchMedia(...)
to update the match state.
import { useEffect, useState } from 'react';export default function useMediaQuery(query: string): boolean {const [matches, setMatches] = useState(() => window.matchMedia(query).matches,);useEffect(() => {const mediaQueryList = window.matchMedia(query);function updateMatch() {setMatches(mediaQueryList.matches);}mediaQueryList.addEventListener('change', updateMatch);return () => {mediaQueryList.removeEventListener('change', updateMatch);};}, [query]);return matches;}
useSyncExternalStore
React's useSyncExternalStore
hook is a better fit as it is meant for syncing React state with external systems, such as subscribing to native browser APIs.
import { useCallback, useSyncExternalStore } from 'react';export default function useMediaQuery(query: string): boolean {const subscribe = useCallback((callback: () => void) => {const mediaQueryList = window.matchMedia(query);mediaQueryList.addEventListener('change', callback);return () => {mediaQueryList.removeEventListener('change', callback);};},[query],);return useSyncExternalStore(subscribe,() => window.matchMedia(query).matches,);}
console.log()
statements will appear here.