Vuejs: watch vs watchEffect

Vuejs: watch vs watchEffect

Vue js is a popular JavaScript framework. Vue js provides programmers with various capabilities to create dynamic and adaptable websites.

There are two primary methods in Vue for monitoring changes to reactive data: watch and watchEffect. Both achieve the same objective of rerunning code in reaction to modifications in reactive data, but they are very different from one another.

To put it briefly, the watch function lets you track changes to particular reactive data and take appropriate action in response. Conversely, watchEffect is a reactive function that keeps track of any reactive dependencies that are used by it automatically.

Watch

Using watch in Vue js, two arguments are supplied. Two types of dependencies exist a callback function that is called back when the dependent changes and a reactive dependency that we want to monitor. Two arguments are supplied to this callback function: the data's old value and its new value.

The deep & immediate Options

deep and immediate are the two optional settings that you can utilize to alter the watch's functionality.

Recursively seeing an object's nested properties is possible with the deep option. By default, a watch only records the reference of an item, not its real properties. This suggests that changing an object's property won't change the reference to the object itself, which means the watch's callback function won't execute.

You can use the immediate option to start the callback function as soon as the watcher is formed. When watch is first formed, by default, the callback function is not executed.

Let me demonstrate by the following code:

<template>
  <main>
    {{ product.price }} = {{ product.quantity }} * 10
    <input v-model="product.quantity" type="number" />
  </main>
</template>

<script>
export default {
  name: "ProductComponent",
  data() {
    return {
      product: {
        price: 10,
        quantity: 1
      }
    };
  },
  watch: {
    product: {
      handler: function (newVal, oldVal) {
        this.product.price = newVal.quantity * 10;
      },
      deep: false,
      immediate: true
    }
  }
};
</script>

What we want is to combine the product.price value depends on the user-selected product. The watch function will run immediately and the product.price will be 10. However, the watch function won’t run ever again, because it is dependent on the whole product object and we don’t change its reference.

Use deep: true to solve the previous issue, or modifier the watcher to depend on the quantity parameter, as below:

watch: {
    "product.quantity": {
      handler: function (newVal, oldVal) {
        this.product.price = newVal * 10;
      }
    }
  }

Composition API allows us to make the watcher observe the refs value changes, so we can avoid using the deep option.

<template>
  <main>
    {{ product.price }} = {{ product.quantity }} * 10
    <input v-model="product.quantity" type="number" />
  </main>
</template>
<script setup>
const product = ref({
  price: 10,
  quantity: 1
});

watch(product.value,
  (newVal, oldVal) => {
        product.value.price = newVal.quantity * 10;
  },{ immediate: true });
</script>

Vue’s watchEffect

In Vue 3, watchEffect is a function that allows you to perform side effects based on reactive dependencies without explicitly declaring them in the function. It automatically tracks reactive dependencies and re-runs the effect whenever any of those dependencies change. It's similar to watch, but with watchEffect, you don't need to explicitly list the dependencies.

We can rewrite the above example with the following syntax:

<template>
  <main>
    {{ product.price }} = {{ product.quantity }} * 10
    <input v-model="product.quantity" type="number" />
  </main>
</template>

<script setup>
const product = ref({
  price: 10,
  quantity: 1
});

// runs on its dependencies (quantity) change
watchEffect(() => {
  product.value.price = product.value.quantity * 10;
});
</script>

In the case above, the pricing value was determined by using watch or watchEffect in response to a change in quantity. In instances such as these, computed property should be utilized rather than watchers. Watchers are mostly employed to monitor side effects, and common uses include:

  • Using an API request

  • Monitoring user activity

  • storing the modified dependency state in a local storage device


Summary

This blog post delves into the distinctions between Vue's watch and watchEffect functions. Both functions enable you to keep an eye on changes in reactive data. The key difference lies in their usage: watch is employed to specifically monitor particular reactive data and carry out actions when those changes occur. On the other hand, watchEffect automatically tracks any reactive dependencies used within it, making it more flexible in handling changes without explicitly specifying them.