useMediaQuery
Hook for checking if a media query matches.
Example
import useMediaQuery from "@/hooks/useMediaQuery";
export default function UseMediaQueryExample() {
const isMobile = useMediaQuery("(max-width: 768px)");
return (
<div className="flex flex-col items-center gap-4 text-ctp-text">
<p>Is mobile: {isMobile ? "true" : "false"}</p>
<p>
Resize the window to see the effect of the media query on the value of
isMobile.
</p>
</div>
);
}
Code
import { useEffect, useLayoutEffect, useState } from "react";
const useIsomorphicLayoutEffect =
typeof window !== "undefined" ? useLayoutEffect : useEffect;
type UseMediaQueryOptions = {
defaultValue?: boolean;
initializeWithValue?: boolean;
};
const IS_SERVER = typeof window === "undefined";
/**
* Hook for checking if a media query matches.
*
* @param {string} query - The media query to check.
* @param {UseMediaQueryOptions} options - Options for the hook.
* @returns {Boolean} matches - A boolean indicating whether the media query matches.
*/
export default 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;
}