| |
| |
| |
| |
|
|
| import * as React from "react"; |
|
|
| const MOBILE_BREAKPOINT = 768; |
|
|
| export function useIsMobile(breakpoint: number = MOBILE_BREAKPOINT) { |
| const [isMobile, setIsMobile] = React.useState<boolean | undefined>( |
| undefined, |
| ); |
|
|
| React.useEffect(() => { |
| if (typeof window === "undefined") { |
| return; |
| } |
|
|
| const mediaQuery = `(max-width: ${breakpoint - 1}px)`; |
| |
| const getIsMobile = () => window.innerWidth < breakpoint; |
|
|
| const updateIsMobile = () => { |
| setIsMobile(getIsMobile()); |
| }; |
|
|
| let mql: MediaQueryList | null = null; |
| let rafId: number | null = null; |
|
|
| mql = window.matchMedia(mediaQuery); |
| |
| const debouncedUpdate = () => { |
| if (rafId !== null) { |
| cancelAnimationFrame(rafId); |
| } |
| rafId = requestAnimationFrame(updateIsMobile); |
| }; |
|
|
| if (mql.addEventListener) { |
| mql.addEventListener("change", debouncedUpdate); |
| } else if (mql.addListener) { |
| mql.addListener(debouncedUpdate); |
| } |
|
|
| window.addEventListener("resize", debouncedUpdate); |
| window.addEventListener("orientationchange", debouncedUpdate); |
|
|
| updateIsMobile(); |
|
|
| return () => { |
| if (rafId !== null) { |
| cancelAnimationFrame(rafId); |
| } |
| |
| if (mql) { |
| if (mql.removeEventListener) { |
| mql.removeEventListener("change", debouncedUpdate); |
| } else if (mql.removeListener) { |
| mql.removeListener(debouncedUpdate); |
| } |
| } |
|
|
| window.removeEventListener("resize", debouncedUpdate); |
| window.removeEventListener("orientationchange", debouncedUpdate); |
| }; |
| }, [breakpoint]); |
|
|
| return typeof isMobile === "boolean" ? isMobile : false; |
| } |
|
|