The Vue 3 Composition API provides two primary mechanisms for managing state changes: ref and reactive. Both leverage JavaScript proxies under the hood to track mutations and trigger UI updates, yet they serve distinct structural purposes within component logic.
Tracking Object State with reactive
The reactive() method transforms plain JavaScript objects or arrays into deeply observable structures. Any mutation performed on nested properties automatically propagates to subscribed views.
import { reactive } from 'vue'
const settings = reactive({
theme: 'dark',
notifications: {
email: true,
push: false
}
})
// Direct property assignment triggers re-render
settings.theme = 'light'
settings.notifications.push = true
This approach is particularly efficient for grouping related data. Since the entire target becomes a proxy, destructuring requires explicit conversion via toRefs to maintain reactivity; otherwise, isolated variables lose their tracking capability.
Wrapping Values with ref
Conversely, ref is designed to hold primitive values such as numbers, booleans, or strings, though it can also wrap complex types. Accessing or modifying these values requires interacting with the underlying .value property inside script blocks.
import { ref } from 'vue'
const itemQuantity = ref(0)
const isActive = ref(false)
// Mutation requires explicit .value access
itemQuantity.value += 1
isActive.value = true
When wrapping an object, ref maintains reactivity by exposing that object through its .value getter/setter. This pattern is mandatory for standalone primitives and prefered when a value might be reassigned entirely rather than mutated in place. Additionallly, ref serves as the standard conduit for capturing DOM node references during template mounting.
Structural Considerations for Selection
Choosing between these patterns hinges on data organization requirements:
- Opt for
reactivewhen dealing with interconnected datasets that require in-place property modifications without unwrapping overhead. It scales well for configuration states, form models, or deeply nested hierarchies where every sub-property needs tracking. - Choose
reffor standalone primitives, values destined for complete reassignment, or scenarios requiring explicit reference management. Its uniform wrapper behavior also simplifies serialization operations since the internal proxy logic remains encapsulated behind.value.