Ref vs reactive in Vue.js
ref vs reactive
Vue 3 Composition API provides two main ways to create reactive state: ref and reactive. Understanding their differences is essential for writing correct Vue code.
ref
ref wraps a value in a reactive object with a .value property:
vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
const name = ref('Alice')
const user = ref({ name: 'Alice', age: 25 })
// Access/mutate via .value in script
count.value++
name.value = 'Bob'
user.value.age = 26
// Can reassign the whole value
user.value = { name: 'Charlie', age: 30 }
</script>
<template>
<!-- .value is automatically unwrapped in templates -->
<p>{{ count }}</p>
<p>{{ name }}</p>
</template>reactive
reactive creates a deeply reactive proxy of an object:
vue
<script setup>
import { reactive } from 'vue'
const state = reactive({
count: 0,
user: { name: 'Alice', age: 25 },
items: ['a', 'b', 'c']
})
// Access directly β no .value needed
state.count++
state.user.name = 'Bob'
state.items.push('d')
// β Cannot reassign the whole object!
// state = { count: 1 } // This breaks reactivity!
</script>
<template>
<p>{{ state.count }}</p>
<p>{{ state.user.name }}</p>
</template>Key Differences
| Feature | ref | reactive |
|---|---|---|
| Works with | Any type (primitives + objects) | Objects only (no primitives) |
| Access in script | .value required | Direct access |
| Access in template | Auto-unwrapped | Direct access |
| Reassignment | β
Can reassign .value | β Cannot reassign whole object |
| Destructuring | β Works (keeps reactivity) | β Loses reactivity |
| TypeScript | Ref<T> type | Original type |
The Destructuring Problem
vue
<script setup>
import { reactive, toRefs } from 'vue'
const state = reactive({ name: 'Alice', age: 25 })
// β Destructuring loses reactivity!
let { name, age } = state
name = 'Bob' // NOT reactive β won't update the template
// β
Use toRefs to keep reactivity
const { name: nameRef, age: ageRef } = toRefs(state)
nameRef.value = 'Bob' // β
Reactive!
</script>When to Use Which
Primitive value (string, number, boolean)?
β ref
Want to replace the entire value?
β ref
Object/array you only mutate properties of?
β reactive (or ref β both work)
Simple component state?
β ref (most common, recommended by Vue team)Common Pattern: ref for Everything
The Vue team recommends using ref as the default:
vue
<script setup>
import { ref } from 'vue'
// β
Consistent β always use ref
const count = ref(0)
const name = ref('Alice')
const users = ref([{ name: 'Alice' }, { name: 'Bob' }])
const form = ref({ email: '', password: '' })
</script>Important:
ref works with any type and requires .value in script. reactive works only with objects and provides direct access. The Vue team recommends ref as the default because it's more flexible (supports primitives, allows reassignment). Use reactive when you prefer dot-notation for complex state objects.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.