Frontend Development 10 min read

Why ref Is Preferred Over reactive in Vue 3: Limitations of reactive and Best Practices

This article explains the fundamental differences between Vue 3's reactive and ref APIs, highlighting reactive's limitation to objects, the situations where it loses reactivity, and why using ref—along with techniques like Object.assign and toRefs—provides more reliable and flexible state management.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Why ref Is Preferred Over reactive in Vue 3: Limitations of reactive and Best Practices

The Vue 3 reactive API can only wrap reference types (objects and arrays), while ref can wrap any value type, including primitives, objects, and arrays. Because of this, reactive often loses reactivity when the whole object is reassigned, when properties are destructured, or when the reactive object is passed to a function.

Key comparison:

reactive
ref

❌ Supports only objects/arrays

✅ Supports primitives + reference types

✅ Can be used directly in

<script>

and

<template>

❌ Requires

.value

in

<script>

(template accesses value automatically)

❌ Reassigning a new object drops reactivity

✅ Reassigning a new object keeps reactivity

❌ Direct property access works

❌ Must use

.value

to read/write

❌ Passing to a function loses reactivity

✅ Passing to a function retains reactivity

❌ Destructuring loses reactivity (needs

toRefs

)

❌ Same issue; use

toRefs

after

ref

if needed

Common pitfalls with reactive and solutions:

Do not replace the whole reactive object; assign properties individually. let state = reactive({ count: 0 }) // wrong – loses reactivity state = { count: 1 } // correct state.count = 1

Use Object.assign to merge new values without breaking the proxy. state = Object.assign(state, { count: 1 })

When you need to replace the whole object, prefer ref : let state = ref({ count: 0 }) state.value = { count: 1 } // works

For destructuring, use toRefs so each property remains a ref . const state = reactive({ count: 0 }) let { count } = toRefs(state) count.value++ // updates state.count

When passing reactive data to functions, pass the property itself or use ref to keep tracking. function fn(val) { console.log(val) } fn(state.count) // loses tracking // use ref instead let count = ref(state.count) fn(count.value)

Because ref requires the .value suffix, many developers rely on IDE plugins (e.g., Volar) to auto‑complete this boilerplate, making the code easier to write while still clearly indicating reactive variables.

In summary, ref offers a broader applicability, fewer pitfalls, and clearer intent, making it the recommended API for most Vue 3 state‑management scenarios.

frontendJavaScriptVueReactiveVue3ref
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.