0
0
Vueframework~15 mins

Shallow ref and shallow reactive in Vue - Deep Dive

Choose your learning style9 modes available
Overview - Shallow ref and shallow reactive
What is it?
In Vue, shallow ref and shallow reactive are special ways to make data reactive but only at the top level. This means Vue tracks changes to the main object or value, but not inside nested objects or arrays. They help control reactivity performance and behavior by limiting how deep Vue watches for changes.
Why it matters
Without shallow ref or shallow reactive, Vue tracks changes deeply inside objects and arrays, which can slow down apps and cause unexpected updates. These shallow versions let developers optimize performance and avoid unnecessary reactivity on complex nested data. Without them, apps might feel slow or behave unpredictably when working with big or complex data.
Where it fits
Before learning shallow ref and shallow reactive, you should understand Vue's basic reactivity system, including ref and reactive. After this, you can explore advanced reactivity patterns, performance optimization, and Vue's reactivity internals.
Mental Model
Core Idea
Shallow ref and shallow reactive make Vue track changes only on the outer layer of data, ignoring nested parts.
Think of it like...
It's like putting a fence around your garden's main yard but not around each flower bed inside. You notice if the yard gate opens or closes, but you don't watch every flower's movement.
┌───────────────┐
│ Shallow Reactivity │
├───────────────┤
│ Outer object   │  ← Vue watches this
│ ┌───────────┐ │
│ │ Nested obj │  ← Vue ignores this
│ └───────────┘ │
└───────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Vue Reactivity Basics
🤔
Concept: Learn how Vue tracks changes in data using ref and reactive.
Vue's ref creates a reactive wrapper around a simple value, like a number or string. Reactive wraps an object or array and tracks changes deeply inside it. When data changes, Vue updates the UI automatically.
Result
You can create reactive data that updates the UI when changed.
Understanding basic reactivity is essential because shallow versions build on this but limit how deep Vue watches.
2
FoundationDifference Between ref and reactive
🤔
Concept: Know when to use ref for primitives and reactive for objects.
ref is for single values and reactive is for objects or arrays. Both make data reactive but reactive tracks nested changes deeply, while ref tracks the whole value.
Result
You can choose the right reactive wrapper based on data type.
Knowing this helps you understand why shallow versions exist to control reactivity depth.
3
IntermediateIntroducing shallowRef and shallowReactive
🤔Before reading on: do you think shallowRef tracks nested changes or only top-level changes? Commit to your answer.
Concept: Vue provides shallowRef and shallowReactive to track only the top-level changes, ignoring nested data.
shallowRef wraps a value but does not make nested objects reactive. shallowReactive wraps an object but only tracks changes to the outer object, not inside nested objects or arrays.
Result
Vue updates UI only when the outer value or object changes, ignoring nested mutations.
Understanding shallow reactivity helps optimize performance by avoiding deep tracking when unnecessary.
4
IntermediateWhen to Use shallowRef vs shallowReactive
🤔Before reading on: do you think shallowRef can wrap objects like shallowReactive? Commit to your answer.
Concept: shallowRef is for any value but tracks only the top level, while shallowReactive is specifically for objects and tracks only their top-level properties.
Use shallowRef when you want a reactive reference but don't want nested reactivity. Use shallowReactive when you want a reactive object but only track changes to its immediate properties.
Result
You can pick the right shallow reactive tool based on your data structure and needs.
Knowing the difference prevents bugs and improves app performance by choosing the correct shallow reactive type.
5
IntermediateEffect of Nested Changes on UI Updates
🤔Before reading on: if you change a nested property inside a shallowReactive object, will Vue update the UI? Commit to your answer.
Concept: Nested changes inside shallow reactive data do not trigger UI updates because Vue does not track them deeply.
If you mutate a nested object inside shallowReactive, Vue ignores it. Only changes to the outer object or reference trigger updates.
Result
UI stays the same when nested data changes unless the outer reference changes.
This behavior helps avoid unnecessary UI updates but requires careful data management.
6
AdvancedPerformance Benefits of Shallow Reactivity
🤔Before reading on: do you think shallow reactivity always improves performance? Commit to your answer.
Concept: Shallow reactivity reduces the overhead of tracking deep nested changes, improving performance especially with large or complex data.
Deep reactivity requires Vue to create proxies for every nested object, which can be slow. Shallow reactive skips this, so Vue only watches the top-level object or value.
Result
Apps with large nested data run faster and use less memory when using shallow reactive.
Understanding this tradeoff helps you optimize apps by balancing reactivity depth and performance.
7
ExpertCaveats and Internal Behavior of Shallow Reactivity
🤔Before reading on: do you think shallowReactive proxies nested objects or just the root? Commit to your answer.
Concept: Internally, shallow reactive creates a proxy only for the root object, leaving nested objects as plain JavaScript objects without proxies.
Vue's reactivity system uses proxies to track changes. shallowReactive creates a proxy for the outer object but returns nested objects as-is, so nested mutations are invisible to Vue's reactivity system.
Result
Developers must manually replace nested objects to trigger updates or use deep reactive if nested tracking is needed.
Knowing this internal detail prevents bugs where nested changes don't update the UI and guides correct usage.
Under the Hood
Vue uses JavaScript proxies to intercept get and set operations on objects. For shallowReactive, Vue creates a proxy only for the top-level object. When you access nested properties, Vue returns the original nested objects without proxies. Therefore, changes inside nested objects are not detected. For shallowRef, Vue wraps the value but does not recursively make nested objects reactive. This reduces the number of proxies and tracking overhead.
Why designed this way?
Vue's deep reactivity can cause performance issues with large or complex nested data. Shallow reactive variants were introduced to give developers control over reactivity depth. This design balances reactivity power with performance and predictability. Alternatives like deep reactive tracking were too costly in some cases, so shallow reactive offers a lighter option.
┌───────────────┐
│ shallowReactive│
├───────────────┤
│ Proxy (root)  │
│ ┌───────────┐ │
│ │ Nested obj │ (plain object, no proxy)
│ └───────────┘ │
└───────────────┘

Accesses to nested obj go directly to original object without reactivity.
Myth Busters - 4 Common Misconceptions
Quick: Does shallowReactive track changes inside nested objects? Commit yes or no.
Common Belief:shallowReactive tracks all nested changes just like reactive.
Tap to reveal reality
Reality:shallowReactive only tracks changes to the outer object; nested changes are ignored.
Why it matters:Assuming nested changes trigger updates leads to bugs where UI does not update as expected.
Quick: Can shallowRef only wrap primitive values? Commit yes or no.
Common Belief:shallowRef is only for primitive values like numbers or strings.
Tap to reveal reality
Reality:shallowRef can wrap any value, including objects, but only tracks the top-level reference.
Why it matters:Misusing shallowRef limits flexibility and causes confusion about reactivity behavior.
Quick: Does using shallowReactive always improve app speed? Commit yes or no.
Common Belief:Using shallowReactive always makes apps faster.
Tap to reveal reality
Reality:shallowReactive improves performance only when deep reactivity is unnecessary; otherwise, it can cause stale UI.
Why it matters:Blindly using shallowReactive can cause UI bugs and stale data if nested changes are important.
Quick: Does shallowReactive automatically convert nested objects to reactive? Commit yes or no.
Common Belief:shallowReactive automatically makes nested objects reactive too.
Tap to reveal reality
Reality:shallowReactive leaves nested objects as plain JavaScript objects without reactivity.
Why it matters:Expecting nested reactivity causes confusion and bugs when nested changes don't update the UI.
Expert Zone
1
shallowReactive proxies only the root object, so replacing nested objects triggers updates, but mutating nested properties does not.
2
shallowRef is useful for wrapping complex objects that should not be deeply reactive but still need to trigger updates when replaced.
3
Using shallow reactivity requires careful manual management of nested data to ensure UI stays in sync.
When NOT to use
Avoid shallow ref and shallow reactive when you need Vue to track deep nested changes automatically. Use reactive or ref for full deep reactivity instead. Also, avoid shallow reactive if your app relies heavily on nested mutations triggering UI updates.
Production Patterns
In production, shallow reactive is often used for large state objects where only top-level changes matter, such as caching or external data wrappers. shallowRef is used when storing complex objects that change entirely but don't need deep tracking, like third-party library instances or DOM elements.
Connections
Immutable Data Structures
shallow reactivity complements immutable data by tracking only top-level references, similar to how immutable data changes require replacing whole objects.
Understanding shallow reactivity helps grasp how immutable patterns optimize UI updates by avoiding deep change detection.
Proxy Pattern (Software Design)
Vue's reactivity system uses JavaScript proxies to intercept operations; shallow reactive creates proxies only at the root level.
Knowing the proxy pattern clarifies how shallow reactive limits interception to top-level, improving performance.
Cache Invalidation in Web Systems
shallow reactive's top-level tracking is like cache invalidation strategies that only refresh data when main keys change, ignoring nested details.
This connection shows how shallow reactivity balances update frequency and performance, similar to caching.
Common Pitfalls
#1Expecting nested changes in shallowReactive to update UI.
Wrong approach:const state = shallowReactive({ user: { name: 'Alice' } }); state.user.name = 'Bob'; // UI does not update
Correct approach:const state = shallowReactive({ user: { name: 'Alice' } }); state.user = { name: 'Bob' }; // UI updates
Root cause:Misunderstanding that shallowReactive does not track nested mutations, only top-level replacements.
#2Using shallowRef for deeply reactive needs.
Wrong approach:const data = shallowRef({ items: [1, 2, 3] }); data.value.items.push(4); // UI does not update
Correct approach:const data = ref({ items: [1, 2, 3] }); data.value.items.push(4); // UI updates
Root cause:Confusing shallowRef with ref; shallowRef does not make nested objects reactive.
#3Assuming shallowReactive improves performance in all cases.
Wrong approach:const bigData = shallowReactive(largeNestedObject); // Mutating nested data expecting fast updates
Correct approach:const bigData = reactive(largeNestedObject); // Use reactive if nested updates are needed despite performance cost
Root cause:Overgeneralizing shallowReactive benefits without considering nested update needs.
Key Takeaways
Shallow ref and shallow reactive limit Vue's reactivity to the top-level data only, ignoring nested changes.
They help improve performance by reducing the number of proxies Vue creates and tracks.
Using shallow reactive requires careful management of nested data to ensure UI updates correctly.
Choosing between shallow and deep reactivity depends on whether nested changes need to trigger UI updates.
Understanding shallow reactivity internals prevents common bugs and helps optimize Vue applications.