DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk4 min

Vue 3 State: When ref() or reactive() Fits Your Code

Vue recommends ref() as the default for Composition API state. Learn when reactive() fits better, and avoid the proxy replacement and destructuring pitfalls.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For Vue 3 Composition API state, use ref() by default: it works with primitives and objects, and Vue recommends it as the primary API for declaring reactive state. Choose reactive() when a stable, object-shaped value is easier to work with through direct property access. The key tradeoff is .value syntax versus keeping and using the same reactive proxy.

Quick comparison: ref() and reactive()

Question ref() reactive()
What can it hold? Primitives such as numbers, strings and booleans, as well as objects. Objects, including arrays and collection types such as Map and Set; not primitives.
How do you access it in JavaScript? Through .value, such as count.value++. Through properties on the returned proxy, such as state.count++.
What becomes reactive? The ref and its value; object values are deeply converted by default. The returned proxy and its properties; nested objects are converted deeply as accessed.
Can you replace the state container? Yes. Assign a new value to .value. Not while preserving the original proxy connection. Keep using the same proxy.
What is the main gotcha? Remembering .value in JavaScript and that automatic unwrapping depends on context. Replacing the proxy or destructuring a primitive property can disconnect access from reactivity.

Vue’s Reactivity Fundamentals guide says: “Due to these limitations, we recommend using ref() as the primary API for declaring reactive state.”

As an Amazon Associate I earn from qualifying purchases.

Use ref() for most state

A ref wraps a value in a ref object. In JavaScript, read or update the wrapped value with .value. That makes it suitable for primitive state and for values that may be replaced altogether.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { ref } from 'vue'

const count = ref(0)
count.value++

const selectedItem = ref({ name: 'Notebook' })
selectedItem.value = { name: 'Pen' }

When a ref is exposed as a top-level property in a component’s template, Vue automatically unwraps it, so template expressions usually use count rather than count.value. JavaScript code still uses .value.

Use reactive() for a stable object

reactive() returns a Proxy for an object-like value. Read and mutate its properties directly, which can feel natural when related fields form one stable object.

import { reactive } from 'vue'

const form = reactive({
  name: '',
  email: ''
})

form.name = 'Ari'

Vue tracks access through the proxy, not through the original raw object. Use the returned proxy consistently; mutating the original object does not trigger updates through the reactive connection. The Reactivity in Depth guide explains how Vue’s proxy-based tracking works.

Two reactive() pitfalls to avoid

Do not replace the whole proxy

Reactivity is tied to the original proxy reference. Assigning a new object to a variable that previously held the proxy does not transfer that connection to the replacement object. If the state needs whole-value replacement, use a ref and assign the new object to .value.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not destructure primitive properties when you need a live connection

For example, const { count } = state copies the current primitive value into a local binding. Reading or changing that binding no longer accesses the proxy’s count property, so it is disconnected from that property’s reactivity. A different case is an object-valued property: a local variable referring to that nested object can still observe reactive mutations to the object, even though the local binding itself is not a tracked property access.

When Vue unwraps refs—and when it does not

Ref unwrapping depends on where the ref is used. A top-level ref exposed to a template is unwrapped, and a ref used as a property of a deep reactive object is also unwrapped. That behavior does not apply in every context:

  • A ref nested inside a plain object expression in a template may not be unwrapped like a top-level template ref.
  • A ref stored in a reactive array or a native collection such as Map remains a ref; access its value with .value.
  • Properties of a shallow reactive object do not unwrap refs in the way deep reactive properties do.
const count = ref(0)
const state = reactive({ count })
const counts = reactive([count])

state.count // unwrapped value
counts[0].value // ref remains in the array

For details on these context-specific rules, see Vue’s Reactivity API: Core.

When to use shallowRef()

If another system owns an object’s state, or deep conversion is undesirable for a large structure, consider shallowRef(). It makes the ref’s value reactive without deeply converting the inner object. Replace .value when the external state changes so Vue can observe the ref update. Vue describes this pattern in Reactivity in Depth.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Decision cheat sheet

  • Choose ref() for primitives, replaceable values, and state passed through reusable functions when you need to preserve the ref connection.
  • Choose reactive() when an object’s grouped shape is convenient and you can keep using its proxy without replacing it or destructuring primitive properties.
  • Choose shallowRef() when you want to avoid deep conversion, particularly for externally managed state.

In short: start with ref(); reach for reactive() when direct access to a stable object makes the code clearer.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.