use-breakpoint-agent
Version:
A React hook to detect device type based on screen width
34 lines (33 loc) • 1.66 kB
JavaScript
import { useCallback, useMemo, useRef } from "react";
import { DeviceEnum } from "../types/index.js";
import { useSyncExternalStore } from "use-sync-external-store/shim";
import { getDeviceTypeFromString } from "../client.js";
import { defaultBreakpoints } from "../lib/default.js";
export const useBreakpointAgent = (initialServer = undefined, breakpoints) => {
const resize = useRef(false);
const firstWidth = useRef(null);
const { mobile, tablet } = useMemo(() => (Object.assign(Object.assign({}, defaultBreakpoints), breakpoints)), [breakpoints]);
const subscribe = useCallback((listener) => {
window.addEventListener("resize", listener);
return () => window.removeEventListener("resize", listener);
}, []);
const getSnapshot = useCallback(() => {
if (!firstWidth.current)
firstWidth.current = window.innerWidth;
if (!resize.current && firstWidth.current !== window.innerWidth) {
resize.current = true;
const w = window;
w.__breakpointAgent = { firstWidth: firstWidth.current, resize: true };
}
if (!resize.current)
return getDeviceTypeFromString(navigator.userAgent);
const width = window.innerWidth;
if (width <= mobile)
return DeviceEnum.MOBILE;
if (width < tablet)
return DeviceEnum.TABLET;
return DeviceEnum.DESKTOP;
}, [mobile, tablet]);
const getServerSnapshot = useCallback(() => initialServer !== null && initialServer !== void 0 ? initialServer : null, [initialServer]);
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
};