Apps Artificial Intelligence CSS DevOps Go JavaScript Laravel Linux MongoDB MySQL PHP Python Rust Svelte Vue

Understanding Watchers in Vue 3

2 min read .
Understanding Watchers in Vue 3

Vue 3 watchers let you run side-effect logic when reactive data changes. They are useful for tasks such as triggering an API request, synchronizing with an external system, persisting state, or responding to a transition between values.

1. What Is a Watcher?

A watcher observes one or more reactive sources and runs a callback when their values change. Unlike a computed property, which represents derived state, a watcher is usually intended for side effects.

2. Basic Watcher

<template>
  <input v-model="name" placeholder="Enter your name" />
  <p>Your name is: {{ name }}</p>
</template>

<script setup>
import { ref, watch } from 'vue';

const name = ref('');

watch(name, (newValue, oldValue) => {
  console.log(`Name changed from ${oldValue} to ${newValue}`);
});
</script>

The first argument is the reactive source and the second is the callback. For a simple ref, the callback receives the new and previous values.

3. Watchers vs. Computed Properties

Feature Watcher Computed Property
Purpose Run side effects after state changes Derive a value from reactive state
Typical uses API calls, persistence, async work Calculations and display values
Result Callback behavior Cached reactive value

If you only need a value calculated from other state, prefer computed(). Use watch() when something needs to happen because a value changed.

4. deep and immediate Options

Use deep when you need to react to nested mutations within an observed object structure:

<script setup>
import { reactive, watch } from 'vue';

const user = reactive({ profile: { name: 'John', age: 30 } });

watch(
  () => user.profile,
  (newVal) => console.log('Profile updated:', newVal),
  { deep: true }
);
</script>

Use immediate when the callback should run once as soon as the watcher is created:

<script setup>
import { ref, watch } from 'vue';

const counter = ref(0);

watch(
  counter,
  (newVal) => console.log('Watcher triggered:', newVal),
  { immediate: true }
);
</script>

5. Watch Refs and Reactive Object Properties

<script setup>
import { ref, reactive, watch } from 'vue';

const counter = ref(0);
const state = reactive({ name: 'Alice' });

watch(counter, (newVal) => console.log('Counter updated:', newVal));
watch(() => state.name, (newVal) => console.log('Name updated:', newVal));
</script>

For a property on a reactive object, pass a getter function such as () => state.name so Vue can track the intended source.

6. Best Practices

  • Use a computed property instead when the goal is only to derive data.
  • Avoid broad deep watchers when a narrower source can express the same intent.
  • Clean up resources created inside watcher callbacks, especially timers, subscriptions, and async work.
  • Use watcher cleanup APIs or an abort mechanism to prevent stale asynchronous requests from updating newer state.

7. Common Mistakes

  • Passing a non-reactive primitive value instead of a ref or getter.
  • Using deep watching for large object graphs without considering the cost.
  • Starting asynchronous work on every change without cancellation or debouncing.

Conclusion

Watchers are a flexible part of Vue 3’s reactivity system. Use them when a reactive change should trigger an effect, and use computed properties when you simply need another reactive value derived from existing state.

Related Posts

chevron-up