Under The Hood
frontend vue Vue 3.x

ref() .value Box Wrapper vs reactive() Proxy Unwrap

Last updated
Prerequisites:
Vue 3 Composition API
JavaScript Proxy fundamentals
  • vue
  • reactivity
  • ref
  • reactive
  • proxy
  • composition-api

Read at your depth

The practical view

`ref()` wraps any value (primitives like `0`, `'hello'`, or objects) in a `{ value: T }` object. In `<template>`, refs are unwrapped automatically (use `count`), but in `<script>` you must use `count.value`. `reactive()` only accepts objects/arrays and returns a deep Proxy: `state.count`. Destructuring a `reactive()` object (`const { count } = state`) breaks reactivity; use `toRefs(state)` to fix it.

The same idea in other frameworks

react equivalent
`const [count, setCount] = useState(0)` (immutable state values).

Legacy vs modern

Destructuring reactive() (Broken) vs toRefs / ref() (Safe)

Destructuring a `reactive()` object strips Proxy tracking; `ref()` and `toRefs()` preserve live reactivity.

before → after
Destructuring reactive() breaks tracking
const { count } = state; // ❌ Reactivity permanently lost!
Using ref() or toRefs()
const count = ref(0); // ✅ NEW: Safe to pass and destructure

Interview gotchas

Context

This tests JavaScript reference vs primitive value passing and Vue's reactivity mechanics.

The mechanical answer

`reactive()` relies on JavaScript `Proxy` traps (`get` and `set`) on the root object. When you destructure `const { count } = reactive({ count: 0 })`, you are copying the primitive value `0` into a standalone local variable. Plain variables have no getters or setters, so Vue cannot track reads or writes. `toRefs()` converts every property of the reactive object into a separate `ref` whose `.value` getter points back to the original reactive object's property.

Trap

Never use ES6 destructuring directly on a `reactive()` object unless you wrap it with `toRefs()` or `toRef()`.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.