@@ -10,20 +10,35 @@ However, while React has certainly made the *what* easier with the declarative m
10
10
11
11
## What is a logical clock?
12
12
13
+ A logical clock is a monotonically increasing number. Or in other words, an incremented integer: ` i++ ` .
14
+
15
+ We can implement once as a React hook using ` useReducer() ` :
16
+
13
17
``` ts
14
- function useTick () {
18
+ function useTicker () {
15
19
return useReducer (n => n + 1 , 0 );
16
20
}
17
21
```
18
22
23
+ We can wire it up to a button like so:
24
+
25
+ ``` ts
26
+ const [count, advance] = useTicker ();
27
+
28
+ return <>
29
+ <p >You have clicked {count } times < / p >
30
+ <button >Click me ! < / button >
31
+ < / > ;
32
+ ```
33
+
19
34
## Debouncing
20
35
21
36
``` ts
22
- export function useDebouncedTick (duration : number ): readonly [number , EffectCallback ] {
23
- const [count, tick ] = useTick ();
37
+ export function useDebouncedTicker (duration : number ): readonly [number , EffectCallback ] {
38
+ const [count, advance ] = useTicker ();
24
39
25
40
const callback = useMemo (() => {
26
- let timeout = null ;
41
+ let timeout: null | ReturnType < typeof setTimeout > = null ;
27
42
function clear() {
28
43
if (timeout ) {
29
44
clearTimeout (timeout );
@@ -32,19 +47,25 @@ export function useDebouncedTick(duration: number): readonly [number, EffectCall
32
47
}
33
48
return () => {
34
49
clear ()
35
- timeout = setTimeout (tick , duration );
50
+ timeout = setTimeout (advance , duration );
36
51
return clear ;
37
52
};
38
- }, [duration , tick ]);
53
+ }, [duration , advance ]);
39
54
40
55
return [count , callback ];
41
56
}
42
57
```
43
58
44
59
``` ts
45
60
export function useDebouncedEffect(effect : EffectCallback , duration : number , deps : DependencyList ): void {
46
- const [count, tick ] = useDebouncedTick (duration );
47
- useEffect (tick , deps ); // When our deps change, notify our debouncer.
61
+ const [count, receive ] = useDebouncedTicker (duration );
62
+ useEffect (receive , deps ); // When our deps change, notify our debouncer.
48
63
useEffect (effect , [count ]); // When our debouncer finishes, run our effect.
49
64
}
65
+
66
+ export function useDebouncedMemo<T >(factory : () => T , duration : number , deps : DependencyList ): T {
67
+ const [tick, scheduleAdvance] = useDebouncedTicker (duration );
68
+ useEffect (scheduleAdvance , deps ); // When our deps change, notify our debouncer.
69
+ return useMemo (factory , [tick ]); // When our debouncer finishes, invalidate our memo.
70
+ }
50
71
```
0 commit comments