Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 debugging reference for reactivity issues, computed errors, watcher bugs, async failures, and SSR hydration problems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/watch-reactive-property-getter.md
1---2title: Use Getter Function When Watching Reactive Object Properties3impact: HIGH4impactDescription: Watching reactive properties directly passes a primitive value, causing the watcher to never trigger5type: capability6tags: [vue3, watch, watchers, reactive, getter, common-mistake]7---89# Use Getter Function When Watching Reactive Object Properties1011**Impact: HIGH** - Directly watching a property of a reactive object passes a primitive value to `watch()`, not a reactive reference. The watcher will never trigger because primitives are not reactive.1213When you need to watch a specific property of a reactive object, always wrap it in a getter function `() => obj.property`.1415## Task Checklist1617- [ ] Always use getter functions when watching properties of reactive objects18- [ ] Remember that `watch(obj.count, ...)` passes the current value, not a reactive reference19- [ ] For refs, you can watch directly: `watch(myRef, ...)`20- [ ] For entire reactive objects, you can watch directly (creates implicit deep watcher)2122**Incorrect:**23```javascript24import { reactive, watch } from 'vue'2526const state = reactive({ count: 0, name: 'Vue' })2728// WRONG: Passes the number 0 to watch(), not a reactive reference29// This watcher will NEVER fire!30watch(state.count, (newCount) => {31console.log(`Count changed to: ${newCount}`)32})3334// WRONG: Same problem with string property35watch(state.name, (newName) => {36console.log(`Name changed to: ${newName}`)37})38```3940**Correct:**41```javascript42import { reactive, watch } from 'vue'4344const state = reactive({ count: 0, name: 'Vue' })4546// CORRECT: Use a getter function47watch(48() => state.count,49(newCount, oldCount) => {50console.log(`Count changed from ${oldCount} to ${newCount}`)51}52)5354// CORRECT: Multiple properties with getter55watch(56() => state.name,57(newName) => {58console.log(`Name changed to: ${newName}`)59}60)6162// CORRECT: Watching derived values63watch(64() => state.count * 2,65(doubledCount) => {66console.log(`Doubled count: ${doubledCount}`)67}68)69```7071## Watching Multiple Properties7273```javascript74import { reactive, watch } from 'vue'7576const state = reactive({ firstName: 'John', lastName: 'Doe' })7778// Watch multiple properties with array of getters79watch(80[() => state.firstName, () => state.lastName],81([newFirst, newLast], [oldFirst, oldLast]) => {82console.log(`Name changed from ${oldFirst} ${oldLast} to ${newFirst} ${newLast}`)83}84)85```8687## When Direct Watching Works8889```javascript90import { ref, reactive, watch } from 'vue'9192const count = ref(0)93const state = reactive({ nested: { value: 1 } })9495// CORRECT: Refs can be watched directly96watch(count, (newVal) => {97console.log(`Count: ${newVal}`)98})99100// CORRECT: Entire reactive objects create implicit deep watcher101watch(state, (newState) => {102// Fires on any nested change103// Note: newState === oldState (same object reference)104})105```106107## Reference108- [Vue.js Watchers - Watch Source Types](https://vuejs.org/guide/essentials/watchers.html#watch-source-types)109