-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathcustom-hooks.js
70 lines (58 loc) · 1.79 KB
/
custom-hooks.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { useEffect, useRef, useState } from 'react';
export const noop = () => {};
export const useDidUpdate = (callback, deps) => {
const hasMount = useRef(false);
useEffect(() => {
if (hasMount.current) {
callback();
} else {
hasMount.current = true;
}
}, deps);
};
// Usage: const ref = useModalBehavior(() => setSomeState(false))
// place this ref on a component
export const useModalBehavior = (hideOverlay) => {
const ref = useRef({});
// Return values
const setRef = (r) => {
ref.current = r;
};
const [visible, setVisible] = useState(false);
const trigger = () => setVisible(!visible);
const hide = () => setVisible(false);
const handleClickOutside = ({ target }) => {
if (
ref &&
ref.current &&
!(ref.current.contains && ref.current.contains(target))
) {
hide();
}
};
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [ref]);
return [visible, trigger, setRef];
};
// Usage: useEffectWithComparison((props, prevProps) => { ... }, { prop1, prop2 })
// This hook basically applies useEffect but keeping track of the last value of relevant props
// So you can passa a 2-param function to capture new and old values and do whatever with them.
export const useEffectWithComparison = (fn, props) => {
const [prevProps, update] = useState({});
return useEffect(() => {
fn(props, prevProps);
update(props);
}, Object.values(props));
};
export const useEventListener = (
event,
callback,
useCapture = false,
list = []
) =>
useEffect(() => {
document.addEventListener(event, callback, useCapture);
return () => document.removeEventListener(event, callback, useCapture);
}, list);