# watch and computed in Vue 3: when to use which

computed produces a value with no side effects, watch runs code when a source changes. The choice depends on the output: a piece of data or an effect.

> Page: https://ui.eneawork.it/blog/vue-3-watchers-vs-computed
> Markdown: https://ui.eneawork.it/blog/vue-3-watchers-vs-computed.md

*2026-11-01*

Usa computed quando devi ottenere un valore da altro stato e watch quando devi eseguire un effetto: una richiesta, un log, un salvataggio. Se la funzione non restituisce un valore, non è un computed.

Misurato il 1 novembre 2026: il catalogo conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, letti da /api/stats. Su 1.514 profili di libreria 10 riguardano Vue, 8 dei quali dichiarano licenza MIT: la distinzione è la stessa che il catalogo applica nei componenti con filtri e ricerca. Metodo: lettura di data/library_profiles.json e della risposta di /api/stats con uno script Node, sul repository EneUI.

## Computed: un valore derivato

import { computed, ref } from "vue"; const query = ref(""); const rows = ref([]); const visible = computed(() => rows.value.filter((row) => row.name.toLowerCase().includes(query.value.toLowerCase()), ), );

Il filtro gira una volta per cambiamento di query o rows, non a ogni render. computed tiene il risultato in cache finché una dipendenza non cambia: è questa la differenza pratica con un metodo chiamato nel template.

## Watch: un effetto con una sorgente

import { ref, watch } from "vue"; const id = ref("1"); const user = ref(null); watch( id, async (value, _old, onCleanup) => { const controller = new AbortController(); onCleanup(() => controller.abort()); const res = await fetch("/api/users/" + value, { signal: controller.signal, }); user.value = await res.json(); }, { immediate: true }, );

Qui il risultato non è un valore da mostrare ma una richiesta da lanciare. immediate esegue subito, onCleanup annulla la chiamata precedente quando id cambia o il componente smonta.

## La scelta in tre righe

## Errori comuni

## Il limite da mettere in conto

Nessuna delle due funzioni risolve il problema del primo caricamento: un computed asincrono restituisce una Promise, non il dato. Per un valore che arriva dalla rete servono un ref e un watch con cleanup, come nell’esempio sopra.

## Dove continuare

Nel catalogo: shadcn-vue, PrimeVue e Vuetify; le tabelle con filtro sono in components. Le guide: Composition API e Pinia. Il confronto: stato derivato in React e Vue vs React.

## FAQ

### Posso usare computed dentro watch?

Sì, e spesso conviene: watch su un computed reagisce al valore derivato invece che a ogni campo che lo compone.

### watch o watchEffect?

watch dichiara le sorgenti e riceve vecchio e nuovo valore, watchEffect raccoglie le dipendenze da solo ed è comodo per effetti brevi.

### computed può essere asincrono?

No. Una funzione async dentro computed restituisce una Promise e il valore non viene atteso: per un dato asincrono serve watch più un ref.

### Perché il mio watch non parte?

La sorgente non è reattiva. Una funzione getter su una variabile normale non notifica nulla: passa un ref o una funzione che legge un ref.

### Meglio watch con deep?

Solo sugli oggetti che cambi in profondità. Su strutture grandi il costo di traversal supera il beneficio e conviene osservare un campo preciso.
