58 lines
1.2 KiB
TypeScript
58 lines
1.2 KiB
TypeScript
|
|||
|
|
import { useState, useLayoutEffect } from "react";
|
||
|
|
|
||
|
|
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;
|
||
|
|
});
|
||
|
|
|
||
|
|
function handleChange() {
|
||
|
|
setMatches(getMatches(query));
|
||
|
|
}
|
||
|
|
|
||
|
|
useLayoutEffect(() => {
|
||
|
|
const matchMedia = window.matchMedia(query);
|
||
|
|
|
||
|
|
handleChange();
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|