Watch Annotations
Annotations
Section titled “Annotations”@watch
Section titled “@watch”Explicitly mark properties for tracking (shallow comparison): @computed getters, and fields holding an observable.box(), .array(), .map() or .set() instead of being annotated with @observable.
class Model { @watch field = observable.box(false);
constructor() { makeObservable(this); }}A watcher leaves a @computed out unless it is marked (see Computed properties). Here, the prices of the items count through the total, although changes to elements are not tracked on their own:
class Model { @observable items = [{ price: 10 }];
constructor() { makeObservable(this); }
@watch @computed get total() { return this.items.reduce((sum, item) => sum + item.price, 0); }}
const model = new Model();const watcher = Watcher.get(model);
runInAction(() => { model.items[0].price = 20;});
watcher.changedKeys // Set(["total"])@watch.ref
Section titled “@watch.ref”Track with identity comparison only
class Model { @watch.ref @observable items = [1, 2, 3];
constructor() { makeObservable(this); }}
const model = new Model();const watcher = Watcher.get(model);
runInAction(() => { model.items.push(4); // No change detected (same array reference)});
watcher.changed // false@unwatch
Section titled “@unwatch”Exclude properties from tracking
class Model { @unwatch @observable internalState = false; @observable userField = false;
@computed get derivedState() { return this.internalState ? "active" : "inactive"; }
constructor() { makeObservable(this); }}
const model = new Model();const watcher = Watcher.get(model);
runInAction(() => { model.internalState = true; // Not tracked});
watcher.changed // falsewatcher.changedKeys // Set() - derivedState is a @computed, so it is not tracked eitherTracking Nested Objects
Section titled “Tracking Nested Objects”Use @nested to track changes in nested object properties. Read Nested section for detail.
- Each nested object gets its own
Watcherinstance automatically - Nested watchers are independent - calling
reset()on a child watcher doesn't affect the parent
class Parent { @nested @observable child = new Child(); @nested @observable items = [new Item()];
constructor() { makeObservable(this); }}
class Child { @observable value = false;
constructor() { makeObservable(this); }}
const parent = new Parent();const watcher = Watcher.get(parent);
runInAction(() => { parent.child.value = true; parent.items[0].value = true;});
watcher.changed // truewatcher.changedKeys // Set([]) - no direct property changeswatcher.changedKeyPaths // Set(["child.value", "items.0.value"]) - nested change tracked
// Nested watchers are independentconst childWatcher = Watcher.get(parent.child);childWatcher.reset(); // Does NOT affect parent watcherwatcher.changed // still true