UNPKG

1.74 kBJavaScriptView Raw
1import useEffect from './useIsomorphicEffect';
2import { useState } from 'react';
3
4var isBool = function isBool(a) {
5 return typeof a === 'boolean';
6};
7
8var matchers = new Map();
9
10var getMatcher = function getMatcher(query) {
11 if (!query || typeof window == 'undefined') return undefined;
12 var mql = matchers.get(query);
13
14 if (!mql) {
15 mql = window.matchMedia(query);
16 mql.refCount = 0;
17 matchers.set(mql.media, mql);
18 }
19
20 return mql;
21};
22/**
23 * Match a media query and get updates as the match changes. The media string is
24 * passed directly to `window.matchMedia` and run as a Layout Effect, so initial
25 * matches are returned before the browser has a chance to paint.
26 *
27 * ```tsx
28 * function Page() {
29 * const isWide = useMediaQuery('min-width: 1000px')
30 *
31 * return isWide ? "very wide" : 'not so wide'
32 * }
33 * ```
34 *
35 * Media query lists are also reused globally, hook calls for the same query
36 * will only create a matcher once under the hood.
37 *
38 * @param query A media query
39 */
40
41
42export default function useMediaQuery(query) {
43 var mql = getMatcher(query);
44
45 var _useState = useState(function () {
46 return mql ? mql.matches : false;
47 }),
48 matches = _useState[0],
49 setMatches = _useState[1];
50
51 useEffect(function () {
52 var mql = getMatcher(query);
53
54 if (!mql) {
55 return setMatches(false);
56 }
57
58 var handleChange = function handleChange() {
59 setMatches(mql.matches);
60 };
61
62 mql.refCount++;
63 mql.addListener(handleChange);
64 handleChange();
65 return function () {
66 mql.removeListener(handleChange);
67 mql.refCount--;
68
69 if (mql.refCount <= 0) {
70 matchers.delete(mql.media);
71 }
72
73 mql = undefined;
74 };
75 }, [query]);
76 return matches;
77}
\No newline at end of file