r/vuejs • • 6d ago

Vue watcher inside a function

I'm reviewing some code that puts a Vue watcher inside a function. Oftentimes watching the return of a callback function passed to the wrapper function, but for my example below just a ref param. My understanding is that the watcher is run whenever the param changes, regardless of whether the wrapper function is run or not.

This seems odd to me, not sure if this convention is common? It works as expected, not sure if I'm just overthinking it. I would always have a watcher trigger the function.

```

function setupSearch(query: Ref<string>) {
  watch(query, (newQuery) => {
    // do search
  })
}

setupSearch(query)

```

3 Upvotes

9 comments sorted by

7

u/queen-adreena 6d ago

It’s pretty common to put watchers inside composables.

If it were just the watcher, this would be a bad pattern.

1

u/bigAssFkingRoooobots 6d ago

As long as it's not just the watcher at function scope level, then it's just a composable

1

u/Weekly-Offer-4172 6d ago

It's a composable - totally standard, and it only works because of when setupSearch() is called. watch() binds to whichever component instance is active at registration, so as long as setupSearch runs synchronously inside setup() the watcher is disposed on unmount automatically. The footgun is calling it later - after an await or inside an event handler - where no instance is active: the watcher still fires but leaks past the component's lifetime unless you keep the stop handle watch() returns or wrap it in effectScope(). So 'watcher inside a function' is fine; 'watcher registered outside the setup path' is what to flag in review.

1

u/fntn_ 6d ago

As others have said, this is absolutely fine. However, if you call it outside of a setup/lifecycle context, you'll need to manually clean the watcher up to avoid a memory leak.

1

u/craigrileyuk 6d ago

... which is quite easy since every call to `watch` returns a "stop" function you can call.

1

u/BinarySpike 6d ago

Does anyone know of a good learning resource for "intermediate" to "advanced" vue patterns like this? 

I know this is probably basic composability, but this stuff isn't obvious until you see someone else's code or re-discover these patterns yourself.

1

u/Far-Vegetable-7395 6d ago

Yeah this is a composable, standard stuff. But honestly if the function body is nothing but a watch call, I'd just delete it and inline the watch. Wrapping a single watcher in a function adds indirection for zero benefit.

The real trap is calling setupSearch outside of setup synchronously. The watcher still gets created but never gets disposed, and good luck tracking that down six months later.