JAVASCRIPT

Reacting to Data Changes with watch and watchEffect in Vue 3

Execute side effects when reactive data changes using `watch` for specific sources and `watchEffect` for automatic dependency tracking in Vue 3.

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

const count = ref(0);
const name = ref('Alice');
const user = reactive({
  firstName: 'John',
  lastName: 'Doe',
  age: 30
});

// watch a single ref
watch(count, (newCount, oldCount) => {
  console.log(`Count changed from ${oldCount} to ${newCount}`);
  // Perform an action, e.g., fetch data
  if (newCount > 5) {
    console.log('Count is now greater than 5!');
  }
});

// watch multiple refs
watch([name, () => user.firstName], ([newName, newFirstName], [oldName, oldFirstName]) => {
  console.log(`Name changed from "${oldName}" to "${newName}"`);
  console.log(`User first name changed from "${oldFirstName}" to "${newFirstName}"`);
});

// watch a reactive object property (requires a getter function)
watch(() => user.age, (newAge, oldAge) => {
  console.log(`User age changed from ${oldAge} to ${newAge}`);
});

// watch a reactive object deeply
watch(user, (newUser, oldUser) => {
  console.log('User object changed deeply:', newUser, oldUser);
}, { deep: true }); // Important for deep changes

// watchEffect: automatically tracks dependencies
watchEffect(() => {
  console.log(`watchEffect: Current count is ${count.value} and name is ${name.value}`);
  // This effect will re-run whenever count or name changes
});

// Cleanup for watchEffect
const stopWatchEffect = watchEffect((onCleanup) => {
  // Simulate an async operation
  const id = setTimeout(() => {
    console.log(`watchEffect with cleanup: Fetching data for count ${count.value}`);
  }, 1000);

  onCleanup(() => {
    // This will be called before the effect re-runs or component unmounts
    console.log(`watchEffect cleanup: Clearing timeout for count ${count.value}`);
    clearTimeout(id);
  });
});

// Stop a watch manually if needed
// stopWatchEffect();

function increment() {
  count.value++;
}

function changeName() {
  name.value = name.value === 'Alice' ? 'Bob' : 'Alice';
}

function increaseAge() {
  user.age++;
}

function changeLastName() {
  user.lastName = user.lastName === 'Doe' ? 'Smith' : 'Doe';
}
</script>

<template>
  <div>
    <h2>Watchers Example</h2>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment Count</button>

    <p>Name: {{ name }}</p>
    <button @click="changeName">Change Name</button>

    <p>User: {{ user.firstName }} {{ user.lastName }} (Age: {{ user.age }})</p>
    <button @click="increaseAge">Increase Age</button>
    <button @click="changeLastName">Change Last Name (deep watch)</button>

    <p>Check console for watch logs.</p>
  </div>
</template>
How it works: This snippet demonstrates the two primary ways to react to data changes in Vue 3's Composition API: `watch` and `watchEffect`. `watch` allows you to explicitly observe one or more reactive data sources (refs, reactive objects, or getter functions) and execute a callback when they change, providing access to both new and old values. `watchEffect` automatically tracks any reactive dependencies accessed during its initial run and re-executes whenever those dependencies change, also offering a cleanup function for side effects.

Need help integrating this into your project?

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

Hire DigitalCodeLabs