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.
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 = 1Use 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 } // worksFor destructuring, use toRefs so each property remains a ref.
const state = reactive({ count: 0 })
let { count } = toRefs(state)
count.value++ // updates state.countWhen 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
