Why reactive Canât See Numbers: Understanding Primitives in Vueâs Reactivity System
reactive does not work with primitives because it relies on JavaScript Proxy to intercept property access, and primitives have no properties to observe, so Vue cannot track or trigger updates without wrapping them using ref.
At some point, you try something that feels like it should work:
const count = reactive(0)It looks reasonable.
Youâre giving Vue a value and asking it to make it reactive.
But it doesnât work.
And the reason is not a limitation of Vue aloneâ
itâs a limitation of how JavaScript itself works.
Reactivity Is About Observation
Vueâs reactivity system is built on a simple idea:
Observe when something is accessed.
React when something changes.
But thereâs a catch.
To observe something, there must be something to observe.
Not just a valueâ
but a structure.
Objects Have Structure
When you write:
const state = reactive({
count: 0
})Vue wraps that object in a Proxy.
This allows it to intercept:
- when
state.countis read - when
state.countis written
Thereâs a clear relationship:
- target â
state - key â
"count"
And thatâs enough for Vue to track and react.
Primitives Donât
Now compare that to a primitive:
let count = 0There is no structure here.
No keys.
No properties.
No access path like something.count.
Itâs just a value.
And thatâs the problem.
Nothing to Intercept
Vueâs reactivity depends on intercepting operations like:
getâ when a property is accessedsetâ when a property is changed
But with a primitive, there is nothing to intercept.
There is no count.value by default.
No object wrapper.
No key to track.
Just a number.
And a number alone cannot be observed.
The Role of ref
This is where ref comes in.
Instead of trying to make the primitive reactive directly, Vue creates a structure around it:
const count = ref(0)Internally, this behaves like:
{
value: 0
}Now, suddenly, everything changes.
There is a propertyâvalue.
There is a target and a key.
And Vue can finally do what it needs:
Track when value is read.
Trigger updates when value changes.
A Subtle Shift
What ref really does is not just âmake a primitive reactive.â
It gives that primitive a shape.
A form that Vue can observe.
Without that shape, reactivity has nothing to attach to.
Why Not Hide This?
You might wonder:
Why doesnât Vue just handle primitives automatically?
Why not make reactive(0) work?
Because that would blur an important distinction.
Vue keeps the model explicit:
- objects are observed through
reactive - primitives are wrapped through
ref
This clarity helps you understand whatâs actually happening.
Two Ways of Thinking
At this point, the difference becomes clearer.
reactive says:
âI will observe your existing structure.â
ref says:
âI will create a structure so I can observe you.â
They solve the same problemâ
but from opposite directions.
A Final Thought
Reactivity is often described as tracking values.
But thatâs not entirely true.
It doesnât track values directly.
It tracks access to properties.
And primitivesâŚ
donât have properties.
So Vue doesnât fail to make them reactive.
It simply has nothing to work withâ
until you give it something to hold onto.