Vue Watchers: Running Code on State Changes
Vue watchers are tripwires for your data. When a specific piece of state changes, a watcher executes code, like fetching data from an API. Use them for side effects, not for deriving new values. The footgun is using a watcher where a computed property would.
WHY IT EXISTS Sometimes you need to do more than just calculate a new value when state changes. You need to perform an action—a "side effect"—like calling an API, logging an event, or manually changing the DOM. Watchers provide a dedicated, imperative mechanism for this reactive logic.
THE MENTAL MODEL A watcher is an event listener for a specific piece of reactive state. You tell Vue, "Keep an eye on this 'question' ref. The moment its value changes, run this function for me." This is different from a computed property, which is about declaratively defining what a value is, not what to do when another value changes.
HOW IT WORKS In the Composition API, you use the watch() function, passing it a "source" to track and a callback function to execute. The source can be a ref, a reactive object, a getter function, or an array of multiple sources. The callback receives the new and old values as arguments, allowing you to compare them. For example: watch(myRef, (newValue, oldValue) => { ... }). To watch a nested property or an expression, you wrap it in a getter: watch(() => user.profile.name, (newName) => { ... }).
WHEN TO USE IT Use watchers for operations that have side effects. Three common scenarios are: first, performing asynchronous operations like fetching data from an API when a query parameter changes; second, manually manipulating the DOM in response to a state change (though this is less common); and third, performing complex logic that needs to compare the new and old value of the state.
WHEN NOT TO USE IT Avoid watchers for deriving state. If you can calculate a value based on existing state, always use a computed property. Instead of watching firstName and lastName to manually update a fullName ref, create a computed(() => firstName.value + ' ' + lastName.value). Computed properties are more efficient as they cache their results and are more declarative.
ONE CANONICAL EXAMPLE A classic use case is an auto-completing search input. You watch the ref bound to the input field. When the user types, the watcher's callback is triggered. Inside the callback, you can debounce the input and then make an asynchronous API call to fetch search results. The watcher handles the side effect (the API call) in response to the state change (the input value).
Read the original → vuejs.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.