-
Notifications
You must be signed in to change notification settings - Fork 1
/
event.ts
80 lines (73 loc) · 1.73 KB
/
event.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
69
70
71
72
73
74
75
76
77
78
79
80
import { useCallback, useMemo } from "react";
import { useGlobal } from "./global";
interface Listener {
id: string;
name: string;
func: (...args: any[]) => any;
}
interface UseEventOptions<D = Record<string, any>> {
name: string;
initialData?: D;
}
export type Event<D> = {
listeners: Listener[];
} & D;
export function useEvent<D>({ name, initialData }: UseEventOptions<D>) {
const global = useGlobal<{
events: Record<string, Event<D>>;
}>(
{
events: {},
},
(arg) => {
const { events } = arg!;
if (!events[name]) {
events[name] = {
listeners: [],
} as any;
}
if (initialData) {
for (const k of Object.keys(initialData)) {
if (!events[name].hasOwnProperty(k)) {
events[name][k as keyof D] = initialData![k as keyof D] as any;
}
}
}
},
[name]
);
const event = useMemo(() => {
return global.events[name];
}, [global, name]);
const addListener = useCallback(
(name: string, dispatch) => {
const id = `${Math.random()}${new Date().getTime()}`;
event.listeners.push({
id,
name,
func: (...args: any[]) => {
dispatch(...args);
},
});
return () => {
event.listeners = event.listeners.filter((list) => list.id !== id);
};
},
[event]
);
const emit = useCallback(
(name: string, ...args: any[]) => {
for (const listener of event.listeners) {
if (listener.name === name) {
listener.func(...args);
}
}
},
[event]
);
return [event, addListener, emit] as [
Event<D>,
(name: string, ...args: any[]) => any,
(name: string, ...args: any[]) => any
];
}