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
Dirtyflag, 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
Pendingflag, 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 neededEffect 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
SubscriberandDependencyintoReactiveNode - Trigger
unwatched(dep)when all subscribers are lost, without recursively clearing subsequent subscribers propagatenow only propagatesPending; to immediately markDirty, callpropagate+shallowPropagateafter assignment- Adjusted naming for
EffectFlagsandReactiveFlags; removed unused flags
Updated Options and APIs
notifyEffectβnotifyupdateComputedβupdate- Added the
unwatchedoption 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