/
useStoreStateOpt.ts
68 lines (55 loc) · 1.96 KB
/
useStoreStateOpt.ts
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
import { Store } from "./Store";
import { useEffect, useRef, useState } from "react";
import { IUpdateRef } from "./useStoreState";
import { ObjectPath } from "./useStoreStateOpt-types";
let updateListenerOrd = 0;
function fastGet<S extends object>(obj: S, path: any[]): any {
return path.reduce((cur: any = obj, key: string | number) => {
return cur[key];
}, undefined);
}
function getSubStateFromPaths<
T extends readonly unknown[],
S extends object = object,
P extends ObjectPath<S, T> = T extends ObjectPath<S, T> ? T : never
>(store: Store<S>, paths: P): any[] {
const state: any = store.getRawState();
const resp: any[] = [];
for (const path of paths) {
resp.push(fastGet(state, path));
}
return resp;
}
function useStoreStateOpt<
T extends readonly unknown[],
S extends object = object,
P extends ObjectPath<S, T> = T extends ObjectPath<S, T> ? T : never
>(store: Store<S>, paths: any) {
const [subState, setSubState] = useState<any>(() => getSubStateFromPaths(store, paths));
const updateRef = useRef<Partial<IUpdateRef & { ordKey: string }>>({
shouldUpdate: true,
onStoreUpdate: null,
currentSubState: null,
ordKey: `_${updateListenerOrd++}`,
});
updateRef.current.currentSubState = subState;
if (updateRef.current.onStoreUpdate === null) {
updateRef.current.onStoreUpdate = function onStoreUpdateOpt() {
// console.log(`Running onStoreUpdate from useStoreStateOpt ${updateRef.current.ordKey}`);
if (updateRef.current.shouldUpdate) {
setSubState(getSubStateFromPaths(store, paths));
}
};
// store._addUpdateListenerOpt(updateRef.current.onStoreUpdate, updateRef.current.ordKey!, paths);
}
useEffect(
() => () => {
// console.log(`removing opt listener ord:"${updateRef.current.ordKey}"`);
updateRef.current.shouldUpdate = false;
store._removeUpdateListenerOpt(updateRef.current.ordKey!);
},
[]
);
return subState;
}
export { useStoreStateOpt };