Vue Tip: Destructure Props in Composition API Without Losing Reactivity
Michael Hoffmann
@mokkapps
Inside <script setup>
we use the defineProps()
compiler macro to access props:
<script setup lang="ts">
const props = defineProps<{ count: number }>()
</script>
defineProps
is a compiler macro and does not need to be imported.As we all love destructuring objects in JavaScript you might want to try to destructure the props object:
<script setup lang="ts">
const { count } = defineProps<{ count: number }>()
</script>
props
object the reactivity is lost.By destructuring the props
object, the count
variable becomes a primitive value (in our case of type number
) and is no longer a ref
or reactive
object.
You can try it yourself in the following StackBlitz demo. Click the "Increment" button multiple times and you will see that the double count value is not updated and always shows 0
:
The simplest solution is to access props as props.count
in order to retain reactivity:
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps<{ count: number }>()
const doubleCount = computed(() => props.count * 2)
</script>
<template>Double Count: {{ doubleCount }}</template>
Try it yourself, now the double count is correctly increased if the "Increment" button is clicked:
If you cannot live without destructuring Vue provides a special helper toRefs:
<script setup lang="ts">
import { computed, toRefs } from 'vue'
const props = defineProps<{ count: number }>()
const { count } = toRefs(props)
const doubleCount = computed(() => count.value * 2)
</script>
<template>Double Count: {{ doubleCount }}</template>
toRefs(props)
converts a reactive object (in this example props
) to a plain object where each property of the resulting object is a ref
pointing to the corresponding property of the original object. We need to use count.value
inside the computed
property, as it is a ref
.
Here's the StackBlitz demo for toRefs
:
You can also watch the corresponding video:
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 :