Skip to content

Commit 035cad4

Browse files
committed
Rewrite useMediaQuery to use a layout effect
1 parent 2dfc945 commit 035cad4

File tree

1 file changed

+23
-31
lines changed

1 file changed

+23
-31
lines changed

src/hooks/useMediaQuery.ts

+23-31
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,34 @@
11
'use client';
22

3-
import { useEffect, useState } from 'react';
3+
import { useCallback, useState } from 'react';
4+
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
45
import { bindEvent, unbindEvent } from '../utils';
56

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+
);
1111

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]);
3315

16+
useIsomorphicLayoutEffect(() => {
17+
const matchMedia = window.matchMedia(query);
18+
handleChange();
19+
bindEvent(matchMedia, 'change', handleChange);
3420
return () => {
35-
if (_mql && handler) {
36-
unbindEvent(_mql, 'change', handler);
37-
}
21+
unbindEvent(matchMedia, 'change', handleChange);
3822
};
39-
}, [mql, onChange]);
23+
}, [handleChange]);
4024

4125
return matches;
4226
}
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

Comments
 (0)