Just Use ref
ref vs reactive — Which to Pick
Both ref and reactive give you reactive state, but ref handles primitives and reassignment cleanly. The default answer is ref.
What you'll learn
- Know that ref auto-unwraps in templates
- See where reactive trips you up (destructuring)
- Default to ref
You have two reactive primitives in Vue: ref for any value and reactive for objects. They behave similarly when used carefully — but reactive has sharp edges that bite in real code. The modern guidance: just use ref.
What They Look Like
import { ref, reactive } from 'vue'
const count = ref(0)
count.value++ // need .value in script
const user = reactive({ name: 'Ada' })
user.name = 'Bob' // no .value In templates both are used identically — Vue auto-unwraps refs.
Where reactive Breaks
1. Destructuring kills reactivity
const state = reactive({ count: 0 })
const { count } = state // count is now a plain 0, not reactive
state.count++ // count above stays 0 With ref, the wrapping container is preserved when you copy variables around.
2. Reassignment kills reactivity
let state = reactive({ a: 1 })
state = reactive({ a: 2 }) // template never sees the new object With ref, replacing .value works fine:
const state = ref({ a: 1 })
state.value = { a: 2 } // updates flow through 3. Primitives are out
reactive(0) does not work — proxies need an object.
The Heuristic
Default to ref. Reach for reactive only when you have a clearly object-shaped piece of local state that you never destructure or reassign. Even then, refs are fine.
// Idiomatic
const user = ref({ name: 'Ada', age: 36 })
const todos = ref<Todo[]>([])
const isLoading = ref(false) To pass parts of a reactive object around without losing reactivity, use toRef / toRefs — covered in a later lesson.