fbpx

Using Vue watchEffect to Track Reactive Dependencies

There are several cases where we might want to track a reactive dependency, and run a method when it runs. We can do this using a Vue watcher.

Especially when combined with asynchronous API calls, there are hundreds of use cases like

  • Getting an object from database when an ID changes
  • Rerunning an animation when a prop changes
  • So many more!

In Vue3, in addition to the watch method, there’s a new watchEffect method. 

This article will go over the new method, cover how to use it, and check out how it’s different than the existing watcher methods. 

Okay – let’s go!

How does Vue watchEffect work?

watchEffect is one of the ways to track reactive dependencies in Vue3. Essentially, we can just write a method using reactive properties, and whenever one of their values updates, our method will run. 

One thing to note is that watchEffect will also run immediately whenever the component is initialized in addition to running when the dependency changes, so just be careful when trying to access the DOM before it’s mounted.

Let’s check out an example

Let’s look at a really simple sample similar to the one from the Vue documentation.

For this, let’s assume that we have some sort of reactive userID property and just want to log whenever it changes. 

The code would look like this. 

  setup () {
    const userID = ref(0)

    watchEffect(() => console.log(userID))
    
    setTimeout(() => {
      userID.value = 1
    }, 1000)

    /*
      * LOG
      * 0 
      * 1
    */

    return {
      date
    }
  }

So, right when our component is initialized, our watchEffect will run and log the starting value. Then, whenever the value of userID changes, our watchEffect will be triggered. 

Easy enough, right?

Why is it different from watch?

So why does this new watchEffect method even exist when there’s already a watch method? 

There are some key differences. 

watchEffect will run a method whenever any of its dependencies are changed, watch tracks a specific reactive property and will only run when that property changes. 

On the other hand, watch tracks a specific property or properties and will only run when it changes. Also, the way that a watch method is setup, it contains the old value of the property, as well as its updated value. 

Essentially, watchEffect will trigger whenever any of its reactive dependencies change and watch will trigger only when the dependencies we state change. 

Also, watch is lazy so it will only trigger when the dependency changes. watchEffect runs immediately when the component is created and then tracks dependency.

So watch is useful for when…

  • You need to control which dependencies trigger the method
  • You need access to the previous value 
  • You need to lazily perform the method

Of course, I can’t tell you which is best for your project, but just make sure you know the reasons why you’re making a coding design choice.

Some things to look out for

By now, we know the basics of the watchEffect method and how it’s different from the other Vue watch method. So let’s cover some of the more advanced tips. These are some of the things that Vue’s Composition API Reference points out.

1. Props are reactive

This is a handy little piece of knowledge. One great use case is changing other values on a page depending on a prop attribute. 

For example, let’s say we had a SongPlayer component that accepts a songID value as a prop. If we changed our song, we would want to load all the content about it. And we can do this with props. 

It’d look something like this.

  props: {
    songID: String
  },
  setup (props) {
    watchEffect(() => console.log(props.songID))
  }

2. We can invalidate side effects using onInvalidate()

A common use case for using Vue watchEffect will be to make some sort of asynchronous API call whenever a reactive dependency changes. But what happens, if the dependency changes again before our first API call finishes? 

That’s where invalidating side effects come on. 

Our watchEffect method also has an onInvalidate method that runs whenever the method is about to run again OR the watcher is stopped. 

We can stop our asynchronous API call like this. 

watchEffect(() => {
      // async API call
      const apiCall = someAsyncMethod(props.songID)

      onInvalidate(() => {
        // cancel the api call
        apiCall.cancel()
      })
})

3. Stopping a watcher

Another neat thing that we can do is stop a watcher on our own. This could be useful if we want to watch a dependency until it reaches a certain value. If we continued to watch after it hit the target value, we’d just be wasting resources.

Our Vue watchEffect method actually returns a stop method that will stop our watcher.

So we can simply store this as a variable, and call it later on. 

setup (props) {

    let stopWatcher = watchEffect(() => console.log(props.songID))

    stopWatcher()
}

And we’re done!

There you have it! I hope that this quick introduction to Vue watchEffect shows off some of the ways that we can use this handy method in our code. 

If you have any questions, comments, or anything really, just leave a reply down below and I’ll get back to you!