Skip to content

Commit 9edd81d

Browse files
committed
feat: add trigger() function
1 parent 9ba018e commit 9edd81d

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

src/index.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,32 @@ export function effectScope(fn: () => void): () => void {
182182
return effectScopeOper.bind(e);
183183
}
184184

185+
export function trigger(fn: () => void) {
186+
const sub: ReactiveNode = {
187+
deps: undefined,
188+
depsTail: undefined,
189+
flags: ReactiveFlags.Watching,
190+
};
191+
const prevSub = setActiveSub(sub);
192+
try {
193+
fn();
194+
} finally {
195+
setActiveSub(prevSub);
196+
do {
197+
const link = sub.deps!;
198+
const dep = link.dep;
199+
unlink(link, sub);
200+
if (dep.subs !== undefined) {
201+
propagate(dep.subs);
202+
shallowPropagate(dep.subs);
203+
}
204+
} while (sub.deps !== undefined);
205+
if (!batchDepth) {
206+
flush();
207+
}
208+
}
209+
}
210+
185211
function updateComputed(c: Computed): boolean {
186212
++cycle;
187213
c.depsTail = undefined;

tests/trigger.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { expect, test } from 'vitest';
2+
import { computed, effect, trigger, signal } from '../src';
3+
4+
test('should trigger updates for dependent computed signals', () => {
5+
const arr = signal<number[]>([]);
6+
const length = computed(() => arr().length);
7+
8+
expect(length()).toBe(0);
9+
arr().push(1);
10+
trigger(arr);
11+
expect(length()).toBe(1);
12+
});
13+
14+
test('should trigger updates for the second source signal', () => {
15+
const src1 = signal<number[]>([]);
16+
const src2 = signal<number[]>([]);
17+
const length = computed(() => src2().length);
18+
19+
expect(length()).toBe(0);
20+
src2().push(1);
21+
trigger(() => {
22+
src1();
23+
src2();
24+
});
25+
expect(length()).toBe(1);
26+
});
27+
28+
test('should trigger effect once', () => {
29+
const src1 = signal<number[]>([]);
30+
const src2 = signal<number[]>([]);
31+
32+
let triggers = 0;
33+
34+
effect(() => {
35+
triggers++;
36+
src1();
37+
src2();
38+
});
39+
40+
expect(triggers).toBe(1);
41+
trigger(() => {
42+
src1();
43+
src2();
44+
});
45+
expect(triggers).toBe(2);
46+
});

0 commit comments

Comments
 (0)