Javascript is required
·
1 min read
·
349 views

Vue Tip: Optimize Performance Using shallowRef

Vue Tip: Optimize Performance Using shallowRef Image

shallowRef can be used to optimize the reactivity of your Vue application. As you might have guessed, shallowRef is a shallow version of ref().

Let's start by defining a counter state using shallowRef:

Component.vue
1<script setup lang="ts">
2import { shallowRef } from 'vue'
3
4const state = shallowRef({
5  count: 0,
6})
7</script>
8
9<template>
10  <span>Count: {{ state.count }}</span>
11</template>

Now let's try to modify the count value:

Component.vue
1<script setup lang="ts">
2import { shallowRef, watch } from 'vue'
3
4const state = shallowRef({
5  count: 0,
6})
7
8const increment = () => {
9  state.value.count = 2 // ⚠️ doesn't trigger change (watcher & UI update)
10}
11
12watch(state, (newState) => {
13  console.log('new state', newState)
14})
15</script>
16
17<template>
18  <span>Count: {{ state.count }}</span>
19  <button @click="increment">Increment count</button>
20</template>

Be careful

If you click the "Increment count" button the counter in the UI is not updated and the watcher is not fired.

Unlike ref(), the inner value of a shallow ref is stored and exposed as-is, and will not be made deeply reactive. Only the .value access is reactive.

The reactivity is correctly triggered if we pass a complete new value to the .value property:

Component.vue
1<script setup lang="ts">
2import { shallowRef, watch } from 'vue'
3
4const state = shallowRef({
5  count: 0,
6})
7
8const setNewValue = () => {
9  state.value = { count: 2 } // triggers change
10}
11
12watch(state, (newState) => {
13  console.log('new state', newState)
14})
15</script>
16
17<template>
18  <span>Count: {{ state.count }}</span>
19  <button @click="setNewValue">Set new .value</button>
20</template>

shallowRef() is typically used for performance optimizations of large data structures, or integration with external state management systems.

Info

Try it yourself in the following StackBlitz project:

If you liked this Vue tip, follow me on X to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter:

I will never share any of your personal data. You can unsubscribe at any time.