0
0
VueHow-ToBeginner · 4 min read

How to Use shallowRef for Performance in Vue

Use shallowRef in Vue to create a reactive reference that tracks only the top-level object changes, ignoring nested property updates. This improves performance when you don't need deep reactivity on large or complex objects. Replace ref with shallowRef when you want to avoid costly deep reactive tracking.
📐

Syntax

The shallowRef function creates a reactive reference that tracks changes only to the reference itself, not to its nested properties.

Usage:

  • const state = shallowRef(initialValue): Creates a shallow reactive reference.
  • state.value: Access or update the stored value.
javascript
import { shallowRef } from 'vue';

const state = shallowRef({ count: 0 });

// Access nested property (not reactive)
console.log(state.value.count);

// Update the whole object (reactive)
state.value = { count: 1 };
Output
0
💻

Example

This example shows how shallowRef tracks changes only when the whole object is replaced, not when nested properties change. It improves performance by avoiding deep reactivity.

javascript
import { createApp, shallowRef, watch } from 'vue';

const App = {
  setup() {
    const state = shallowRef({ count: 0 });

    watch(state, () => {
      console.log('State changed:', state.value);
    });

    function incrementNested() {
      // This will NOT trigger the watcher because nested change is not reactive
      state.value.count++;
    }

    function replaceObject() {
      // This WILL trigger the watcher because the whole object is replaced
      state.value = { count: state.value.count + 1 };
    }

    return { state, incrementNested, replaceObject };
  },
  template: `
    <div>
      <p>Count: {{ state.value.count }}</p>
      <button @click="incrementNested">Increment Nested</button>
      <button @click="replaceObject">Replace Object</button>
    </div>
  `
};

createApp(App).mount('#app');
Output
<p>Count: 0</p><button>Increment Nested</button><button>Replace Object</button>
⚠️

Common Pitfalls

1. Expecting nested reactivity: shallowRef does not track changes inside nested objects. Updating nested properties won't trigger updates.

2. Using shallowRef when deep reactivity is needed: If you need Vue to react to nested changes, use ref or reactive instead.

3. Forgetting to replace the whole object: To trigger updates, you must assign a new object to shallowRef.value.

javascript
import { shallowRef, ref, watch } from 'vue';

const shallow = shallowRef({ count: 0 });
const deep = ref({ count: 0 });

watch(shallow, () => console.log('shallow changed'));
watch(deep, () => console.log('deep changed'));

// This will NOT trigger shallow watcher
shallow.value.count++;

// This WILL trigger deep watcher
deep.value.count++;
Output
deep changed
📊

Quick Reference

  • Use shallowRef for top-level reactivity only.
  • Use ref for deep reactivity on nested objects.
  • Update whole object to trigger shallowRef watchers.
  • Improves performance by avoiding deep reactive tracking.

Key Takeaways

Use shallowRef to track only top-level changes for better performance with large objects.
Nested property changes inside shallowRef do not trigger reactivity updates.
Replace the entire object assigned to shallowRef.value to trigger watchers.
Use ref or reactive if you need deep reactivity on nested properties.
shallowRef helps avoid unnecessary deep reactive tracking and improves app speed.