In a previous post, we had looked at Vue 3 Watchers with Composition API. In that example, we used the watch() function to watch reactive variables and also getter methods. However, sometimes watch() function is not sufficient. In such as, we need to use Vue 3 WatchEffect.

Basically, the VueJS watch() function is lazy in nature.

The callback function is not called until the watched source is not changed. However, sometimes we may need to execute the callback function in an eager manner. For example, we might have a requirement to fetch some initial data and then re-fetch the data when the state changes. In such cases, the watch() function usage is not appropriate.

In such cases, we should use the Vue 3 WatchEffect. However, before we look at an example of watchEffect, let us look at how to use watch() function for eager mode.

1 – Vue 3 watch() Function for Eager Mode

In case we decide to use watch() function itself for eager mode as well, we will have to write the logic as follows:

const url = ref('')
const data = ref(null)

async function fetchData() {
  const response = await fetch(url.value)
  data.value = await response.json()

// fetch immediately
// ...then watch for url change
watch(url, fetchData)

For example, we might be looking to watch the change in url value. To have eager fetching, we define a function fetchData() where we make a call to the url. Next, we call the function fetchData() followed by a call to the watch() function.

Clearly, this does not appear to be an ideal way to handle the requirement.

2 – Vue 3 WatchEffect Example

We can simplify the above piece of code by using Vue 3 watchEffect() function.

The watchEffect() function allows us to perform a side effect immediately. However, it also automatically tracks the reactive dependencies.

See below example on how to use watchEffect().

watchEffect(async () => {
  const response = await fetch(url.value)
  data.value = await response.json()

Here, the callback will immediately run once. However, it will also start tracking url.value. Whenever there is a change to the url.value, the callback will be triggered again.

Below is a complete example where we use watchEffect() instead of a simple watch() function.

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

const something = ref('')
const greeting = ref('')
const language = ref('')

watchEffect(async (newSomething) => {
  if (newSomething.length > 0) {
    greeting.value = 'Preparing to greeting...'
    try {
      const res = await fetch('')
      const response = await res.json()
      greeting.value = response.greeting
      language.value = response.language
    } catch (error) {
      answer.value = 'Error! Could not reach the API. ' + error

    Say something:
    <input v-model="something" />
  <p>{{ greeting }}</p>

3 – Vue 3 watchEffect vs watch

Both watchEffect and watch allow us to perform side effects reactively. However, there are some key differences between the two functions.

  • The watch() function only tracks the specified watched source. It won’t track anything else within the callback function. On the other hand, watchEffect() tracks every reactive property accessed during synchronous execution. This makes the reactive properties less explicit.
  • The watch() function gets triggered only when the source value actually changes. We also get more control over when the callback executes. However, watchEffect() runs in an eager manner.

At the end of the day, the choice of using one over the other depends on the requirement.

4 – Conclusion

In this post, we look at Vue 3 WatchEffect with examples. Basically, we compared the amount of code required to handle eager fetching in watch() with watchEffect(). Depending on the use-case, one approach can be chosen over the other.

Want to see more VueJS code examples? Check out this post on creating a Vue 3 Carousel.

If you have any comments or queries about this post, please feel free to mention them in the comments section below.

Categories: VueJS


Leave a Reply

Avatar placeholder

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