-
Notifications
You must be signed in to change notification settings - Fork 45.6k
/
CustomHooks.js
155 lines (133 loc) · 3.44 KB
/
CustomHooks.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import * as React from 'react';
import {
createContext,
forwardRef,
Fragment,
memo,
useCallback,
useContext,
useDebugValue,
useEffect,
useState,
} from 'react';
const object = {
string: 'abc',
number: 123,
boolean: true,
null: null,
undefined: undefined,
array: ['a', 'b', 'c'],
object: {foo: 1, bar: 2, baz: 3},
};
function useNestedInnerHook() {
return useState(123);
}
function useNestedOuterHook() {
return useNestedInnerHook();
}
function useCustomObject() {
useDebugValue(object);
return useState(123);
}
function useDeepHookA() {
useDebugValue('useDeepHookA');
useDeepHookB();
}
function useDeepHookB() {
useDebugValue('useDeepHookB');
useDeepHookC();
}
function useDeepHookC() {
useDebugValue('useDeepHookC');
useDeepHookD();
}
function useDeepHookD() {
useDebugValue('useDeepHookD');
useDeepHookE();
}
function useDeepHookE() {
useDebugValue('useDeepHookE');
useDeepHookF();
}
function useDeepHookF() {
useDebugValue('useDeepHookF');
}
const ContextA = createContext('A');
const ContextB = createContext('B');
function FunctionWithHooks(props: any, ref: React$Ref<any>) {
const [count, updateCount] = useState(0);
// eslint-disable-next-line no-unused-vars
const contextValueA = useContext(ContextA);
// eslint-disable-next-line no-unused-vars
const [_, __] = useState(object);
// Custom hook with a custom debug label
const debouncedCount = useDebounce(count, 1000);
useCustomObject();
const onClick = useCallback(
function onClick() {
updateCount(count + 1);
},
[count],
);
// Tests nested custom hooks
useNestedOuterHook();
// eslint-disable-next-line no-unused-vars
const contextValueB = useContext(ContextB);
// Verify deep nesting doesn't break
useDeepHookA();
return <button onClick={onClick}>Count: {debouncedCount}</button>;
}
const MemoWithHooks = memo(FunctionWithHooks);
const ForwardRefWithHooks = forwardRef(FunctionWithHooks);
function wrapWithHoc(Component) {
function Hoc() {
return <Component />;
}
// $FlowFixMe
const displayName = Component.displayName || Component.name;
Hoc.displayName = `withHoc(${displayName})`;
return Hoc;
}
const HocWithHooks = wrapWithHoc(FunctionWithHooks);
export default function CustomHooks() {
return (
<Fragment>
<FunctionWithHooks />
<MemoWithHooks />
<ForwardRefWithHooks />
<HocWithHooks />
</Fragment>
);
}
// Below copied from https://usehooks.com/
function useDebounce(value, delay) {
// State and setters for debounced value
const [debouncedValue, setDebouncedValue] = useState(value);
// Show the value in DevTools
useDebugValue(debouncedValue);
useEffect(
() => {
// Update debounced value after delay
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
// Cancel the timeout if value changes (also on delay change or unmount)
// This is how we prevent debounced value from updating if value is changed ...
// .. within the delay period. Timeout gets cleared and restarted.
return () => {
clearTimeout(handler);
};
},
[value, delay], // Only re-call effect if value or delay changes
);
return debouncedValue;
}
// Above copied from https://usehooks.com/