Learn how Vue tracks changes and updates the DOM automatically.
1What is Reactivity?
Reactivity means that when the state (data) of your application changes, the DOM (UI) updates automatically to reflect that change. You don't have to write document.getElementById('text').innerHTML = newText ever again.
2The `ref()` function
ref() takes an inner value and returns a reactive and mutable ref object, which has a single property .value. You must use .value in JavaScript, but in the <template>, Vue auto-unwraps it.
3The `reactive()` function
reactive() takes an object and returns a proxy of that object. It does not use .value, making the code look like vanilla JS. However, you cannot destructure a reactive object without losing its reactivity.
4Step-by-Step Breakdown
Reactivity is the heart of Vue. When you update a variable, the UI updates automatically. But regular JavaScript variables are NOT reactive.
To make a primitive value (like a Number, String, or Boolean) reactive in the Composition API, we wrap it in a ref.
Which function is used to declare a reactive state for primitive values (like numbers or strings)?
- →reactive
- →ref
- →useState
Wait! If count is a ref, how do you change its value? You MUST access its .value property inside the <script> tag.
How do you modify the underlying value of a ref inside the JavaScript <script setup> block?
- →score.value
- →score.current
- →setScore
In the <template>, however, Vue is smart. It automatically "unwraps" the ref for you, so you don't need to write .value.
What if you have an Object with multiple properties? You can use ref, but Vue provides another tool called reactive specifically for Objects.
Unlike ref, reactive does NOT require .value. You just access the properties directly.
When using reactive to declare an object, do you need to use .value to access its properties?
- →active
- →value.active
Rule of thumb: Use ref() for everything (primitives, arrays, objects). It is the most robust and universal approach in modern Vue 3.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Reactive Live-Region Announcements
A ref like const statusMessage = ref('') bound to an aria-live="polite" region lets screen readers automatically announce asynchronous state changes — like 'Item added to cart' — the instant the ref updates, without manually calling any announcement API.
<div aria-live="polite">{{ statusMessage }}</div>SEO Implications
- 1
Reactive Primitives Are Resolved to Plain Values Before Reaching the Crawler
Whether internal state is stored in a ref or a reactive() object makes no difference to indexing: by the time Vue's server renderer produces the HTML string, every {{ ref.value }} interpolation has already been unwrapped to plain text, so the reactivity mechanism itself is invisible in the response a crawler downloads.
Best Practices
Default to ref() for Everything
Because reactive() loses reactivity when destructured and cannot hold primitive values re-assignably, most Vue style guides now recommend using ref() universally — including for objects and arrays — and reserving reactive() for cases with a strong reason not to.
Frequent Bugs
Destructuring a reactive() object and losing reactivity.
const { name, age } = reactive({ name: 'A', age: 1 }) copies name and age out as disconnected plain values — future mutations to the original object won't update them. Either reference the object's properties directly (state.name) or convert it with toRefs(state) before destructuring.
Real-World Examples
A Multi-Step Form's Local State
A checkout wizard stores its entire draft order in one const order = reactive({ items: [], shipping: null, payment: null }) object, mutating nested fields directly (order.shipping = selected) across three separate step components without ever reassigning the whole object.
const order = reactive({ items: [], shipping: null });
function selectShipping(method) {
order.shipping = method; // direct mutation, fully reactive
}