Version 2.0 rethinks and optimizes the reactive system model, with minimal impact on users who only use the surface APIs. If you extend or deeply utilize alien-signals
, please pay attention to the "Reactive Model Refactor" section.
Changes to Surface APIs
- Added four new APIs:
getCurrentSub
,setCurrentSub
,getCurrentScope
,setCurrentScope
Deferred Signal Value Evaluation
Differences from v1
In v1, assigning a value to a signal immediately propagated the
Dirty
flag, causing some computed values to be unnecessarily re-evaluated.
// v1
const src = signal(10);
const double = computed(() => src() * 2);
double(); // -> 20
src(999); // double.flags -> Dirty
src(10); // no effect
double(); // -> 20 (recomputed unnecessarily)
In v2, assigning a value to a signal only propagates the
Pending
flag, reducing unnecessary recomputation. Actual evaluation occurs during the next read.
// v2
const src = signal(10);
const double = computed(() => src() * 2);
double(); // -> 20
src(999); // src.flags -> Dirty, double.flags -> Pending
src(10); // no effect
double(); // Checks src state -> unchanged, no recomputation needed
Effect Scope Parent-Child Hierarchy
In v2, recursive cleanup is achieved through a parent-child structure:
const scope1 = effectScope(() => {
const scope2 = effectScope(() => {
effect(() => ...);
computed(() => ...);
});
});
scope1();
Calling scope1()
automatically cleans up its child scope scope2
.
To make scope2
independent of scope1
, temporarily set activeScope = undefined
manually:
const scope1 = effectScope(() => {
const prev = setCurrentScope(undefined);
const scope2 = effectScope(() => {
effect(() => ...);
computed(() => ...);
});
setCurrentScope(prev);
});
Reactive Model Refactor
- Merged
Subscriber
andDependency
intoReactiveNode
- Trigger
unwatched(dep)
when all subscribers are lost, without recursively clearing subsequent subscribers propagate
now only propagatesPending
; to immediately markDirty
, callpropagate
+shallowPropagate
after assignment- Adjusted naming for
EffectFlags
andReactiveFlags
; removed unused flags
Updated Options and APIs
notifyEffect
βnotify
updateComputed
βupdate
- Added the
unwatched
option for custom handling when all subscribers are lost - Removed
processEffectNotifications
,processComputedUpdate
,processPendingInnerEffects
,updateDirtyFlag
- Added
unlink
,checkDirty
For performance differences, please refer to js-reactivity-benchmark.
Contributors
- @johnsoncodehk
- @sxzz
- @medz
- @wangshunnn
- @jh-leong
- @akshar-dave
- @transitive-bullshit
- @PuruVJ
- @amb26
- @tomByrer
- @zhangenming
- @yamanoku
- @Nicell
- @AimWhy
- @Mox93