What does `ref()` do?
1. What ref() does
The ref() function creates a reactive wrapper (container) around any value - a primitive or an object -
and returns an object with a special .value property.
import { ref } from 'vue'
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1Key idea:
ref()makes a value reactive by placing it inside an object of the form{ value: ... }.
Vue "watches" changes to .value,
and automatically updates the template or effects that depend on that value.
2. What reactive() does
reactive(), on the other hand, makes an entire object reactive (through a Proxy).
import { reactive } from 'vue'
const state = reactive({
count: 0,
user: { name: 'Tim' }
})
state.count++ // reactive
state.user.name = 'Alex' // reactiveVue tracks all properties of the object, nesting, and operations on them (get, set, delete, push, etc.).
3. The main difference
| Characteristic | ref() | reactive() |
|---|---|---|
| What it makes reactive | A single value (usually a primitive) | The whole object |
| Syntax | count.value | state.count |
| Works with primitives | Yes | No |
| Works with objects | Yes (wraps internally with reactive()) | Yes |
| Returns | An object { value: ... } | A Proxy object |
| Nested properties | Not reactive (unless ref/reactive is used inside) | Automatically reactive |
| When to use | Simple state, counters, boolean flags | Complex structures, objects, arrays |
| In a Vue template | .value not needed (automatic unwrapping) | Regular dot access |
4. Visually
ref(0)
↓
{ value: 0 } → reactive value
reactive({ count: 0 })
↓
Proxy({ count: 0 }) → reactive object5. How ref() works internally
ref() is implemented through the same mechanism as reactive(), but simpler:
function ref(rawValue) {
let value = reactive(rawValue) // if it's an object, make it reactive
const r = {
get value() {
track(r, 'value')
return value
},
set value(newVal) {
if (newVal !== value) {
value = reactive(newVal)
trigger(r, 'value')
}
}
}
return r
}In other words, ref() is just an object with a getter and a setter
that tracks access to .value and notifies dependent effects when it changes.
6. When to use which
| Scenario | What to use |
|---|---|
Primitive values (number, string, boolean) | ref() |
Complex objects (object, array, map) | reactive() |
| Need to store a single value and change it | ref() |
| Need to manage an entire state | reactive() |
Need to destructure (for example, when returning from setup()) | Prefer ref() (so reactivity is not lost) |
7. A pitfall: destructuring
If you destructure a reactive object, reactivity is lost:
const state = reactive({ count: 0 })
const { count } = state
count++ // not reactiveBecause count is now just a plain number, not a Proxy.
ref(), on the other hand, does not lose reactivity when destructured,
because the value is stored in .value:
const count = ref(0)
const { value } = count
// but in a Vue template this is not needed: {{ count }} automatically takes count.value8. You can combine ref and reactive
Vue automatically unwraps a ref inside a reactive:
const count = ref(0)
const state = reactive({ count })
console.log(state.count) // no .value needed
state.count++ // works and updates count.value tooIn other words, reactive() "understands" ref() and makes access to it convenient.
9. In the template (template)
-
In the template you do not need to write
.value:javascript<template> <p>{{ count }}</p> <!-- automatically takes count.value --> </template>
Vue automatically "unwraps" a ref inside templates.
10. Summary
| Criterion | ref() | reactive() |
|---|---|---|
| What it's for | Primitive values | Objects and arrays |
| Result type | { value: ... } | Proxy |
| Nested objects | Not reactive (needs manual handling) | Deeply reactive |
| Convenient for | Simple state, fields, flags | Complex data structures |
| Auto-unwrap in templates | Yes | Not needed |
| Loses reactivity on destructuring | No | Yes |
Briefly:
ref()makes a single value reactive (usually a primitive).reactive()makes the entire object reactive (and all its contents).Together they give full control over state:
ref()is targeted,reactive()is structural.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.