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/reactive-destructuring.md
1---2title: Never Destructure reactive() Objects Directly3impact: HIGH4impactDescription: Destructuring reactive objects breaks reactivity - changes won't trigger updates5type: capability6tags: [vue3, reactivity, reactive, composition-api, destructuring]7---89# Never Destructure reactive() Objects Directly1011**Impact: HIGH** - Destructuring a `reactive()` object breaks the reactive connection. Updates to destructured variables won't trigger UI updates, leading to stale data display.1213Vue's `reactive()` uses JavaScript Proxies to track property access. When you destructure, you extract primitive values from the proxy, losing the reactive connection. This is especially dangerous when destructuring from composables or imported state.1415## Task Checklist1617- [ ] Never destructure reactive objects directly if you need reactivity18- [ ] Use `toRefs()` to convert reactive object properties to refs before destructuring19- [ ] Consider using `ref()` instead of `reactive()` to avoid this pitfall entirely20- [ ] When importing state from composables, check if it's reactive before destructuring2122**Incorrect:**23```javascript24import { reactive } from 'vue'2526const state = reactive({27count: 0,28name: 'Vue'29})3031// WRONG: Destructuring breaks reactivity32const { count, name } = state3334// These updates work on the original state...35state.count++ // state.count is now 13637// ...but the destructured variables are NOT updated38console.log(count) // Still 0! Lost reactivity39```4041```javascript42// WRONG: Destructuring from a composable43function useCounter() {44const state = reactive({ count: 0 })45return state46}4748const { count } = useCounter() // count is now a non-reactive primitive49```5051**Correct:**52```javascript53import { reactive, toRefs } from 'vue'5455const state = reactive({56count: 0,57name: 'Vue'58})5960// CORRECT: Use toRefs() to maintain reactivity61const { count, name } = toRefs(state)6263state.count++64console.log(count.value) // 1 - Reactivity preserved! (note: now needs .value)65```6667```javascript68// CORRECT: Return toRefs from composables69function useCounter() {70const state = reactive({ count: 0 })71return toRefs(state) // Now safe to destructure72}7374const { count } = useCounter() // count is now a ref, reactivity preserved75```7677```javascript78// ALTERNATIVE: Just use ref() to avoid the issue entirely79import { ref } from 'vue'8081const count = ref(0)82const name = ref('Vue')8384// No destructuring needed, no gotchas85```8687## Reference88- [Vue.js Reactivity Fundamentals - reactive()](https://vuejs.org/guide/essentials/reactivity-fundamentals.html#reactive)89- [Vue.js Reactivity API - toRefs()](https://vuejs.org/api/reactivity-utilities.html#torefs)90