·
1 min read

Vue Tip: Destructure Props in Composition API Without Losing Reactivity

Vue Tip: Destructure Props in Composition API Without Losing Reactivity Image

Inside <script setup> we use the defineProps() compiler macro to access props:

DoubleCount.vue
<script setup lang="ts"> const props = defineProps<{ count: number }>() </script>

Info

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:

DoubleCount.vue
<script setup lang="ts"> const { count } = defineProps<{ count: number }>() </script>

Danger

When you destructure the 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:

DoubleCount.vue
<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:

DoubleCount.vue
<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:

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