Vue 3ReactivityJavaScriptFrontend

Vue 3 Reactivity: ref, reactive, and toRefs

Choose between ref, reactive, and toRefs in Vue 3 by looking at primitive values, objects, destructuring, and whether reactivity must survive extraction.

·Updated ·8 min read·Counting...
Vue 3 Reactivity: ref, reactive, and toRefs

The most common Vue 3 reactivity confusion is practical, not theoretical: why does a primitive value need ref, when should an object use reactive, and why does destructuring sometimes make reactivity disappear?

Once those three questions are clear, ref, reactive, and toRefs become much easier to choose.

What reactivity means in Vue 3

Reactivity means Vue can track reads and writes, then update the view when tracked data changes. Vue 3 uses JavaScript Proxy behavior for objects and wrapper objects for values that cannot be proxied directly.

Use ref for primitive values

Primitive values such as strings, numbers, and booleans are passed by value. Vue needs a wrapper it can track:

import { ref } from "vue"

const count = ref(0)
count.value = 1

Use ref for:

  • counters
  • booleans
  • selected IDs
  • input strings
  • values returned from composables

In templates, Vue unwraps refs automatically. In JavaScript or TypeScript code, use .value.

Use reactive for objects

Objects and arrays are reference values, and Vue can proxy their properties:

import { reactive } from "vue"

const state = reactive({
  count: 0,
  user: { name: "Vue" },
})

state.count = 1
state.user.name = "Vue 3"

Use reactive when several fields belong to one state object, such as a form, panel state, or local component model.

Why destructuring can lose reactivity

Directly destructuring a reactive object breaks the tracked property access:

const state = reactive({ count: 0, name: "Vue" })
const { count, name } = state

count and name are now ordinary local values. They are not connected to state updates in the way you usually expect.

Use toRefs when you need to destructure while keeping each property connected:

import { reactive, toRefs } from "vue"

const state = reactive({ count: 0, name: "Vue" })
const { count, name } = toRefs(state)

Now count and name are refs that stay linked to the original reactive object.

What toRefs solves

toRefs converts each property of a reactive object into a ref connected to the original object.

It is useful when:

  • returning state from a composable
  • passing individual fields around
  • destructuring for template or setup usage

It is not a reason to make every state object more complex. Use it when destructuring is actually needed.

Practical rule

Data shape Prefer
one primitive value ref
one object with related fields reactive
destructured properties from a reactive object toRefs
reusable composable return values often refs or toRefs

Avoid wrapping a single number in reactive. Avoid making every object a ref if it forces awkward .value.deep.property access everywhere.

Subscribe to FreeMac

Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.