On This Page
Reactive Controls
reaction() provides the Reaction instance as the first argument, which can be used to control when and whether the reaction runs.
reaction((computation) => { console.log('Current value:', mySignal.get());});Stopping a Reaction
reaction.stop() permanently prevents a reaction from running again, even if its Signal dependencies change.
From the Return Value
reaction() returns the reaction instance, so you can stop it externally.
const counter = signal(0);
const watcher = reaction(() => { console.log('Count:', counter.get());});
counter.increment(); // reaction runswatcher.stop();counter.increment(); // no longer updatingFrom Inside the Callback
The reaction instance is also passed as the first argument, so it can stop itself based on a condition.
const percentComplete = signal(0);reaction((computation) => { const currentPercent = percentComplete.get(); if(currentPercent >= 100) { computation.stop(); return; } console.log('Progress:', currentPercent);});
percentComplete.increment(80);percentComplete.increment(20); // at 100, reaction stopspercentComplete.increment(50); // no longer updatingSkipping First Run
Reactions run immediately when created to discover their dependencies. Use reaction.firstRun to skip side effects during this initial execution.
const score = signal(0);
reaction((computation) => { const currentScore = score.get(); if (!computation.firstRun) { console.log(`Score: ${currentScore}`); }});Dependency Pitfall
Signal accesses must be reachable during the first run to register as dependencies. A common mistake is returning early on the first run, which prevents any dependencies from being established.
const score = signal(0);
// reaction wont rerun when score changes because dependency is not establishedreaction((computation) => { if (computation.firstRun) { return; } console.log(`Score: ${score.get()}`);});Suppressing Reactivity
Nonreactive
nonreactive() reads reactive values inside a reaction without creating dependencies.
const name = signal('Alice');const status = signal('Online');
reaction(() => { const currentName = name.get(); // dependency created const currentStatus = nonreactive(() => status.get()); // no dependency console.log(`${currentName} is ${currentStatus}`);});
name.set('Bob'); // triggers reactionstatus.set('Offline'); // does not trigger reactionPeek
signal.peek() reads a single signal’s value without creating a dependency. Same effect as nonreactive but scoped to one value.
const counter = signal(0);const trigger = signal(false);
reaction(() => { trigger.get(); // dependency created const currentCount = counter.peek(); // no dependency console.log('Count:', currentCount);});
counter.set(1); // does not trigger reactiontrigger.set(true); // triggers reactionSee Reactive Performance for
guard, which optimizes reactivity for specific patterns.