1 | import useEffect from './useIsomorphicEffect';
|
2 | import { useState } from 'react';
|
3 | const matchersByWindow = new WeakMap();
|
4 | const getMatcher = (query, targetWindow) => {
|
5 | if (!query || !targetWindow) return undefined;
|
6 | const matchers = matchersByWindow.get(targetWindow) || new Map();
|
7 | matchersByWindow.set(targetWindow, matchers);
|
8 | let mql = matchers.get(query);
|
9 | if (!mql) {
|
10 | mql = targetWindow.matchMedia(query);
|
11 | mql.refCount = 0;
|
12 | matchers.set(mql.media, mql);
|
13 | }
|
14 | return mql;
|
15 | };
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | export default function useMediaQuery(query, targetWindow = typeof window === 'undefined' ? undefined : window) {
|
36 | const mql = getMatcher(query, targetWindow);
|
37 | const [matches, setMatches] = useState(() => mql ? mql.matches : false);
|
38 | useEffect(() => {
|
39 | let mql = getMatcher(query, targetWindow);
|
40 | if (!mql) {
|
41 | return setMatches(false);
|
42 | }
|
43 | let matchers = matchersByWindow.get(targetWindow);
|
44 | const handleChange = () => {
|
45 | setMatches(mql.matches);
|
46 | };
|
47 | mql.refCount++;
|
48 | mql.addListener(handleChange);
|
49 | handleChange();
|
50 | return () => {
|
51 | mql.removeListener(handleChange);
|
52 | mql.refCount--;
|
53 | if (mql.refCount <= 0) {
|
54 | matchers == null ? void 0 : matchers.delete(mql.media);
|
55 | }
|
56 | mql = undefined;
|
57 | };
|
58 | }, [query]);
|
59 | return matches;
|
60 | } |
\ | No newline at end of file |