Skip to content

Watchers

watch lets a component react to changes in its own state.

Each watcher is keyed by a state property name and receives a context object that includes:

  • newValue the incoming state value after the update
  • oldValue the outgoing state value before the update
  • isInitial whether the watcher is running as part of the initial mount update pass

These properties help you compare values, filter side effects, and decide how to respond to initialization, later updates, or both.

watch: {
count({ newValue, oldValue, isInitial }) {
console.log(newValue, oldValue, isInitial);
},
}

Watchers also run during the initial mount update pass.

The isInitial property in the context object lets you decide whether a watcher should handle initialization, later updates, or both.

watch: {
count({ isInitial, newValue }) {
if (isInitial) return;
console.log("Count changed:", newValue);
},
}

render is the best fit for DOM changes on elements the component has already resolved.

render: {
panel() {
return {
attributes: {
hidden: !this.state.open,
},
};
},
}

However, watch is where imperative DOM work that goes beyond those render outputs should be managed. That includes tasks such as: restructuring DOM nodes, reordering elements, injecting new elements, and removing existing elements.

In other words, if you need to perform DOM work that render is not meant to describe, use watch.

watch: {
open({ isInitial, newValue }) {
if (isInitial) return;
if (newValue) {
const detailsElement = document.createElement("p");
detailsElement.textContent = "Additional details are now visible.";
this.root.append(detailsElement);
} else {
this.root.lastElementChild?.remove();
}
},
}

Use watch for internal side effects such as:

  • logging
  • analytics
  • timers
  • imperative integrations and DOM work
  • syncing non-render concerns to state changes

Watchers are for internal reactions. They belong to the component definition and are best when the component itself needs to respond to its own state changes.