UNPKG

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