React

watch e computed in Vue 3: quando usare quale

computed produce un valore e non ha effetti collaterali, watch esegue codice quando una sorgente cambia: la scelta dipende dall’output, un dato o un effetto.

In sintesi

  • Se la funzione restituisce un valore, è un computed; se esegue un effetto, è un watch.
  • computed mette in cache il risultato e ricalcola solo quando cambia una dipendenza.
  • watch dichiara le sorgenti, riceve vecchio e nuovo valore e accetta cleanup per annullare richieste.

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.

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

CasoVincePerché
Totale del carrellocomputedValore derivato, nessun effetto
Salvataggio automatico della bozzawatchScrive fuori dallo stato, serve un effetto
Titolo della pagina dal nome utentewatchTocca document.title, non un valore
Filtro di una listacomputedCachato e leggibile nel template

Errori comuni

  • Assegnare dentro un computed: il compilatore avvisa e la cache diventa imprevedibile.
  • Usare watchEffect per un valore derivato: raccoglie dipendenze in modo implicito e ricalcola senza controllo.
  • Osservare un oggetto grande con deep: true: il costo di traversal supera il beneficio.
  • Dimenticare il cleanup: due richieste in volo scrivono lo stato nell’ordine sbagliato.

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.

Domande frequenti

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.