-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathuseEffectState.tsx
More file actions
58 lines (47 loc) · 1.46 KB
/
useEffectState.tsx
File metadata and controls
58 lines (47 loc) · 1.46 KB
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
import useEvent from '@rc-component/util/lib/hooks/useEvent';
import * as React from 'react';
import { unstable_batchedUpdates } from 'react-dom';
import channelUpdate from './channelUpdate';
type Updater<T> = T | ((origin: T) => T);
type UpdateCallbackFunc = VoidFunction;
type NotifyEffectUpdate = (callback: UpdateCallbackFunc) => void;
/**
* Batcher for record any `useEffectState` need update.
*/
export function useBatcher() {
// Updater Trigger
const updateFuncRef = React.useRef<UpdateCallbackFunc[]>(null);
// Notify update
const notifyEffectUpdate: NotifyEffectUpdate = callback => {
if (!updateFuncRef.current) {
updateFuncRef.current = [];
channelUpdate(() => {
unstable_batchedUpdates(() => {
updateFuncRef.current.forEach(fn => {
fn();
});
updateFuncRef.current = null;
});
});
}
updateFuncRef.current.push(callback);
};
return notifyEffectUpdate;
}
/**
* Trigger state update by `useLayoutEffect` to save perf.
*/
export default function useEffectState<T extends string | number | object>(
notifyEffectUpdate: NotifyEffectUpdate,
defaultValue?: T,
): [T, (value: Updater<T>) => void] {
// Value
const [stateValue, setStateValue] = React.useState(defaultValue);
// Set State
const setEffectVal = useEvent((nextValue: Updater<T>) => {
notifyEffectUpdate(() => {
setStateValue(nextValue);
});
});
return [stateValue, setEffectVal];
}