|
1 | 1 | 'use client';
|
2 | 2 |
|
3 |
| -import { useEffect, useState } from 'react'; |
| 3 | +import { useCallback, useState } from 'react'; |
| 4 | +import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'; |
4 | 5 | import { bindEvent, unbindEvent } from '../utils';
|
5 | 6 |
|
6 |
| -export function useMediaQuery(query: string, onChange?: Function): boolean { |
7 |
| - const defaultMql = |
8 |
| - typeof window !== 'undefined' ? window.matchMedia(query) : null; |
9 |
| - const [mql, setMql] = useState(defaultMql); |
10 |
| - const [matches, setMatches] = useState(Boolean(mql && mql.matches)); |
| 7 | +export function useMediaQuery(query: string, defaultValue?: boolean): boolean { |
| 8 | + const [matches, setMatches] = useState<boolean>( |
| 9 | + getMatches(query, defaultValue), |
| 10 | + ); |
11 | 11 |
|
12 |
| - useEffect(() => { |
13 |
| - if (typeof window !== 'undefined') { |
14 |
| - setMql(window.matchMedia(query)); |
15 |
| - } |
16 |
| - }, [query]); |
17 |
| - |
18 |
| - useEffect(() => { |
19 |
| - const _mql = mql; |
20 |
| - let handler: EventListenerOrEventListenerObject; |
21 |
| - |
22 |
| - if (_mql) { |
23 |
| - handler = () => { |
24 |
| - setMatches(_mql.matches); |
25 |
| - |
26 |
| - if (onChange) { |
27 |
| - onChange(_mql.matches); |
28 |
| - } |
29 |
| - }; |
30 |
| - |
31 |
| - bindEvent(_mql, 'change', handler); |
32 |
| - } |
| 12 | + const handleChange = useCallback(() => { |
| 13 | + setMatches(getMatches(query, defaultValue)); |
| 14 | + }, [query, defaultValue]); |
33 | 15 |
|
| 16 | + useIsomorphicLayoutEffect(() => { |
| 17 | + const matchMedia = window.matchMedia(query); |
| 18 | + handleChange(); |
| 19 | + bindEvent(matchMedia, 'change', handleChange); |
34 | 20 | return () => {
|
35 |
| - if (_mql && handler) { |
36 |
| - unbindEvent(_mql, 'change', handler); |
37 |
| - } |
| 21 | + unbindEvent(matchMedia, 'change', handleChange); |
38 | 22 | };
|
39 |
| - }, [mql, onChange]); |
| 23 | + }, [handleChange]); |
40 | 24 |
|
41 | 25 | return matches;
|
42 | 26 | }
|
| 27 | + |
| 28 | +const getMatches = (query: string, defaultValue?: boolean): boolean => { |
| 29 | + if (typeof window !== 'undefined') { |
| 30 | + return window.matchMedia(query).matches; |
| 31 | + } else { |
| 32 | + return defaultValue || false; |
| 33 | + } |
| 34 | +}; |
0 commit comments