ref vs reactive — Which to Pick

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.

4 min read Level 2/5 #vue#refs#reactive
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.

shallowRef & triggerRef →