JAVASCRIPT

Reacting to Data Changes with Vue 3 Watchers (`watch` and `watchEffect`)

Implement Vue 3 watchers (`watch` and `watchEffect`) to perform side effects in response to reactive data changes, with deep watching and immediate options.

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

const counter = ref(0);
const searchTerm = ref('');
const userData = ref({ name: 'Alice', age: 30 });
const message = ref('');

// Using `watch` to react to a specific ref change
watch(counter, (newVal, oldVal) => {
  console.log(`Counter changed from ${oldVal} to ${newVal}`);
  message.value = `Counter is now ${newVal}`;
  // Perform side effect, e.g., save to localStorage, make an API call
  if (newVal > 5) {
    console.log('Counter exceeded 5!');
  }
});

// Using `watch` with multiple sources (array) and deep option
watch([searchTerm, () => userData.value.age], ([newSearch, newAge], [oldSearch, oldAge]) => {
  console.log(`Search term changed from '${oldSearch}' to '${newSearch}'`);
  console.log(`User age changed from ${oldAge} to ${newAge}`);
  // Simulate fetching data based on search term or age
  if (newSearch.length > 2) {
    console.log(`Searching for '${newSearch}'...`);
  }
  if (newAge < 18) {
    console.warn('User is underage!');
  }
}, { deep: true, immediate: true }); // `immediate: true` runs the watcher immediately on setup

// Using `watchEffect` for automatic dependency tracking
// Runs immediately, and re-runs whenever any reactive dependency inside it changes.
watchEffect(() => {
  const currentName = userData.value.name;
  console.log(`WatchEffect: User's current name is ${currentName}.`);
  // This will re-run if userData.value.name changes
  // If `counter.value` was also used here, it would also become a dependency.
});

function incrementCounter() {
  counter.value++;
}

function changeNameAndAge() {
  userData.value.name = 'Bob';
  userData.value.age = 15; // Triggers age watcher
}
</script>

<template>
  <div>
    <h1>Vue 3 Watchers Example</h1>
    <p>Counter: {{ counter }}</p>
    <button @click="incrementCounter">Increment Counter</button>
    <p v-if="message">{{ message }}</p>

    <hr />

    <input type="text" v-model="searchTerm" placeholder="Enter search term" />
    <p>Current Search Term: {{ searchTerm }}</p>

    <hr />

    <p>User Name: {{ userData.name }}</p>
    <p>User Age: {{ userData.age }}</p>
    <button @click="changeNameAndAge">Change User Name & Age</button>
  </div>
</template>
How it works: Vue 3 provides `watch` and `watchEffect` to perform side effects in response to changes in reactive state. `watch` explicitly takes one or more reactive sources (a ref, reactive object, or getter function) and a callback. It receives both the new and old values and gives fine-grained control over when it runs (e.g., `deep` for nested object changes, `immediate` to run on initial setup). `watchEffect`, on the other hand, automatically tracks its reactive dependencies during its first execution. It re-runs whenever any of those tracked dependencies change, making it simpler for scenarios where you just need to react to whatever state is used inside the effect.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs