Watching Changes
Managing State
Section titled “Managing State”Reset the watcher to clear all tracked changes:
const watcher = Watcher.get(model);
runInAction(() => { model.name = "John";});
watcher.changed // truewatcher.changedKeys // Set(["name"])
// Clear all tracked changeswatcher.reset();
watcher.changed // falsewatcher.changedKeys // Set()watcher.changedTick // 0nMark the watcher as changed without incrementing the tick (useful for external state synchronization):
watcher.assumeChanged();
watcher.changed // truewatcher.changedTick // 0n (not incremented)Observing Changes
Section titled “Observing Changes”The changedTick property is a counter that increments with each tracked change.
class Model { @observable name = ""; @observable age = 0;
constructor() { makeObservable(this); }
@computed get displayName() { return `${this.name} (${this.age})`; }}
const model = new Model();const watcher = Watcher.get(model);
watcher.changedTick // 0n
runInAction(() => { model.name = "John";});
// Each change increments the tickwatcher.changedTick // 2n (one for name, one for displayName)watcher.changedKeys // Set(["name", "displayName"])
watcher.reset();
// After reset, both changedKeys and changedTick are clearedwatcher.changedKeys // Set()watcher.changedTick // 0nMost useful with reaction() to trigger side effects when changes occur:
const model = new Model();const watcher = Watcher.get(model);
// React to any tracked changesreaction( () => watcher.changedTick, () => { // Process changes here... saveToBackend(model); });
runInAction(() => { model.name = "John"; model.age = 30;});// Reaction triggers once after the transaction completesTemporarily Disable Tracking
Section titled “Temporarily Disable Tracking”Use unwatch() as a function to run code without changes being detected by Watcher.
const model = new Model();const watcher = Watcher.get(model);
// Changes inside unwatch() are not trackedunwatch(() => { model.name = "John"; model.age = 30;});
watcher.changed // false
// Normal changes are still trackedrunInAction(() => { model.name = "Jane";});
watcher.changed // true⚠️ Warning about transactions: When used inside a transaction, watching only resumes when the outermost transaction completes. This is a fundamental limitation of the implementation.
runInAction(() => { model.field1 = true; // Tracked: Before unwatch begins
unwatch(() => { model.field2 = true; // Not tracked });
model.field3 = true; // ⚠️ NOT tracked: Still in the same transaction as unwatch});// The transaction completes here; watching finally resumes
watcher.changedKeys // Set(["field1"])