SkillByAIOpen interactive version →

Lesson 6 / 25

watch and watchEffect

Running side effects when state changes.

Explicit sources versus automatic tracking

Watchers run side effects (fetching data, writing to localStorage, logging) in response to state changes. watch(source, callback, options) watches an explicit source (a ref, a getter function, a reactive object or an array of these) and receives the new and old values; it is lazy by default, and { immediate: true } runs it once at the start, while { deep: true } watches nested changes. watchEffect(fn) runs immediately and automatically tracks every reactive value read during its run. Both return a stop function, and watchers created synchronously in <script setup> stop automatically when the component unmounts. Newer options such as once depend on your version, so check the docs.

Watching a getter and auto-tracking

Persist a setting and react to a search term.

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

const query = ref('')
const theme = ref(localStorage.getItem('theme') ?? 'light')

// explicit source, new and old values
watch(query, (newQ, oldQ) => {
  console.log(`search changed from "${oldQ}" to "${newQ}"`)
})

// a getter as the source, run once immediately
watch(() => query.value.trim().length, (len) => {
  console.log('length', len)
}, { immediate: true })

// tracks theme automatically because it is read inside
watchEffect(() => {
  localStorage.setItem('theme', theme.value)
})
</script>

Watch a getter for a reactive property

watch(state.count, ...) passes a plain number, which cannot be watched. Write watch(() => state.count, ...) instead.

Quick check: How does watchEffect know what to watch?

  • It only watches props
  • You pass an array of dependencies
  • It watches every ref in the component
  • It tracks the reactive values read while its function runs
Answer

It tracks the reactive values read while its function runs — Automatic dependency tracking.