Chapter 16: Vue Watchers

Vue Watchers in Vue 3 (the modern Composition API way that’s standard in 2026). This is one of those tools that feels a bit “magic” at first but becomes your best friend for handling side effects when data changes.

Watchers let you react to changes in reactive data (ref, reactive, computed, props, etc.) by running some code (a “side effect”) — things like:

  • Fetching data from an API when a search term changes
  • Saving form data to localStorage when it updates
  • Updating the page title or document favicon
  • Logging analytics
  • Syncing state between components or stores

Unlike computed (which returns a value and is cached/pure), watchers are imperative — they run code for its effects, not to produce a value.

In Vue 3 Composition API (<script setup>), we mainly use two functions:

  • watch(source, callback, options?) → precise control
  • watchEffect(callback, options?) → automatic & immediate

Let’s break it down step by step with real examples.

1. Basic watch() – Watching One or More Sources

vue

Key points about watch():

  • Takes source first (ref / getter / array of them)
  • Callback gets newValue, oldValue (and onCleanup function if needed)
  • Lazy by default → doesn’t run immediately on mount
  • Precise → only triggers when the watched source changes
  • Can watch:
    • Single ref → watch(count, …)
    • Getter → watch(() => user.value.name, …)
    • Reactive object property → watch(() => state.user.name, …)
    • Array of sources → watch([count, name], ([newC, newN], [oldC, oldN]) => …)

2. watchEffect() – Automatic Dependency Tracking

vue

Key differences from watch():

Feature watch(source, cb) watchEffect(cb)
When it runs first time Lazy (no, unless immediate: true) Immediate (runs right away)
Dependencies Explicit (you specify what to watch) Automatic (whatever reactive is accessed)
Gets old/new value Yes (new, old) No
Best for Precise control, need old value, one source Side effects depending on many sources
Cleanup function Yes (onCleanup in cb) Yes (return cleanup fn from cb)
Common use API calls on search change Sync title, log, DOM updates

3. Important Options for Both

JavaScript
  • deep: true → useful but expensive for large objects → prefer getters for specific paths
  • flush: ‘post’ → run after DOM update (good for DOM measurements)

4. Cleanup (Important for Async / Subscriptions)

JavaScript

Or in watchEffect:

JavaScript

5. Real-World Pattern: Debounced Search (Common in 2026)

JavaScript

(Or use lodash.debounce / tiny-debounce composable in real apps)

Quick Summary Table – When to Choose What

Goal Use This Why
Run side effect when specific ref changes watch(ref, cb) Precise, get old/new value
Need old value or immediate: false watch(…)
Sync title / log / multiple deps side effect watchEffect(cb) Automatic deps, immediate
Cancel previous async on new change watch + onCleanup Explicit control
Watch nested property without deep:true watch(() => obj.prop, …) Better perf

Pro Tips from Hyderabad 2026 Devs

  • Prefer watch over watchEffect when possible → more explicit, easier to debug
  • Avoid heavy logic in watchers → prefer computed for derived state
  • Use composables to extract watcher logic (e.g. useDebouncedSearch())
  • Watchers can cause infinite loops → be careful mutating watched source inside callback
  • Vue Devtools shows watcher triggers beautifully

Practice challenge: Build a live currency converter:

  • Watch baseAmount + fromCurrency → fetch rate → update result
  • Use watchEffect to update document title with current rate

Any part unclear? Want full async search with abort + debounce example? Or watch vs computed deep comparison? Or how to watch props / route changes?

Just tell me — we’ll go deeper step by step 🚀

Happy watching (reactively) from Hyderabad! 💙

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *