Skip to content

Commit

Permalink
refactor useMediaQuery hook for improved media query handling
Browse files Browse the repository at this point in the history
  • Loading branch information
michaltarasiuk committed Dec 22, 2024
1 parent d571cc3 commit daba00c
Showing 1 changed file with 29 additions and 43 deletions.
72 changes: 29 additions & 43 deletions packages/ui/src/hooks/use-media-query.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,40 @@
import { useEffect, useState } from "react";
import { useCallback, useSyncExternalStore } from "react";

function getDevice(): "mobile" | "tablet" | "desktop" | null {
if (typeof window === "undefined") return null;
type MediaQuery = `(${string}:${string})`;

return window.matchMedia("(min-width: 1024px)").matches
? "desktop"
: window.matchMedia("(min-width: 640px)").matches
? "tablet"
: "mobile";
function getMediaQueryMatch(query: MediaQuery) {
return window.matchMedia(query).matches;
}

function getDimensions() {
if (typeof window === "undefined") return null;

return { width: window.innerWidth, height: window.innerHeight };
function addMediaQueryListener(query: MediaQuery, onChange: () => void) {
const mediaQueryList = window.matchMedia(query);
mediaQueryList.addEventListener("change", onChange);
return function cleanup() {
mediaQueryList.removeEventListener("change", onChange);
};
}

export function useMediaQuery() {
const [device, setDevice] = useState<"mobile" | "tablet" | "desktop" | null>(
getDevice(),
function useMediaQuerySync(query: MediaQuery) {
const subscribeToMediaQuery = useCallback(
(onChange: () => void) => addMediaQueryListener(query, onChange),
[query],
);
const [dimensions, setDimensions] = useState<{
width: number;
height: number;
} | null>(getDimensions());

useEffect(() => {
const checkDevice = () => {
setDevice(getDevice());
setDimensions(getDimensions());
};

// Initial detection
checkDevice();

// Listener for windows resize
window.addEventListener("resize", checkDevice);

// Cleanup listener
return () => {
window.removeEventListener("resize", checkDevice);
};
}, []);
const matches = useSyncExternalStore(
subscribeToMediaQuery,
function getSnapshot() {
return getMediaQueryMatch(query);
},
function getServerSnapshot() {
return false;
},
);
return matches;
}

export function useMediaQuery() {
return {
device,
width: dimensions?.width,
height: dimensions?.height,
isMobile: device === "mobile",
isTablet: device === "tablet",
isDesktop: device === "desktop",
isDesktop: useMediaQuerySync("(min-width: 1024px)"),
isTablet: useMediaQuerySync("(min-width: 640px) and (max-width: 1023px)"),
isMobile: useMediaQuerySync("(max-width: 639px)"),
};
}

0 comments on commit daba00c

Please sign in to comment.