-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathsignal.ts
More file actions
60 lines (48 loc) · 1.17 KB
/
signal.ts
File metadata and controls
60 lines (48 loc) · 1.17 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
59
60
// Ryan's implementation from https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p
const context: any = [];
export type ReadableSignal<T> = () => T;
export interface WritableSignal<T> extends ReadableSignal<T> {
set(value: T): void;
}
export type Effect = () => void;
export function signal<T>(value: T): WritableSignal<T> {
const subscriptions = new Set<any>();
const read = (): T => {
const running = context[context.length - 1];
if (running) {
subscriptions.add(running);
running.dependencies.add(subscriptions);
}
return value;
};
const set = (nextValue: T) => {
value = nextValue;
for (const sub of [...subscriptions]) {
sub.execute();
}
};
(read as any).set = set;
return read as WritableSignal<T>;
}
function cleanup(running) {
for (const dep of running.dependencies) {
dep.delete(running);
}
running.dependencies.clear();
}
export function effect(fn: Effect) {
const execute = () => {
cleanup(running);
context.push(running);
try {
fn();
} finally {
context.pop();
}
};
const running: any = {
execute,
dependencies: new Set()
};
execute();
}