Vue 3.5+: How to Destructure Props in 2024 (Composition API)
Introduction
Directly destructuring props
containing reactive states wasn't feasible in versions of Vue below 3.5.0 because Vue would lose track of changes to the props. To avoid this, developers had to either use the toRefs()
helper function to safely destructure props
, or had to access the props directly through props.key
. However, with Vue 3.5.0 and later versions, destructuring props is now possible without loosing reactivity.
In This Guide
This guide demonstrates how to destructure props
in Vue 3.5+ and higher by implementing a simple counter. It also covers the alternative methods using toRefs()
helper function and direct access through the props object for Vue versions below 3.5.0. The Composition API and the <script setup>
syntax are used throughout this guide.
Setup
- Vue 3.5.0
- Vite 5.4.2
- Node.js 20.14.0
Prerequisites
- Basic understanding of Vue 3, the Composition API and the
<script setup>
syntax. - Node.js is installed on your machine
- A fresh Vue 3 project (version 3.5.0 or higher)
Destructuring props
in Vue 3.5.0 and Higher
Given a fresh Vue 3 project, we implement a simple counter. Update the <App>
component as follows:
<script setup lang="ts">
import ExponentialCount from "@/components/ExponentialCount.vue";
import { ref } from "vue";
const count = ref<number>(0);
</script>
<template>
<div>
Single count: {{ count }}
<ExponentialCount :single-count="count"/>
<button @click="count++">increment</button>
</div>
</template>
Explanation of App.vue
- A reactive state
count
is declared with an initial value of0
(line 5). - Each time the
<button>
is clicked, the value ofcount
is incremented by the handler (line 12). - The value of
count
is displayed in the template and updates automatically (line 10). - The reactive state
count
is passed to the custom child component<ExponentialCount :single-count="count">
(line 11). Sincecount
is not a static value,:
is prepended to the prop name.
Next, create a new file ExponentialCount.vue
in the components/
directory with the following code:
<script setup lang="ts">
import { computed } from 'vue';
const { singleCount } = defineProps<{ singleCount: number }>();
const exponentialCount = computed(() => singleCount * 2);
</script>
<template>
<div>
Exponential count: {{ exponentialCount }}
</div>
</template>
Explanation of ExponentialCount.vue
- The
singleCount
prop is destuctured fromdefineProps(…)
(line 4), instead of assigning it to a variable (such asconst props = defineProps(…);
}). In Vue versions below 3.5.0singleCount
would now lose reactivity. - To illustrated reactivity is maintained, the reactive state
singleCount
is raising by the power of two (line 5) and assigned toexponentialCount
. exponentialCount
is displayed in the template (line 10).
In Vue 3.5.0 and higher, destructuring singleCount
directly like this doesn’t lose reactivity. Each time the increment
button is clicked, the reactive state in count
is incremented and passed to the child component, where it is destructured without losing reactivity.
Destructuing Props in Vue below 3.5.0
In Vue below 3.5.0 destructuring props
would still break reactivity. It is therefore necessary to assign props to a variable for direct access of to make use of the toRefs()
helper function.
Accessing the props
Object Directly
<script setup lang="ts">
import { computed } from 'vue';
const props = defineProps<{ singleCount: number }>();
const exponentialCount = computed(() => props.singleCount * 2);
</script>
<template>
<div>
Exponential count: {{ exponentialCount }}
</div>
</template>
Here, the props
are assigned to a variable (line 4) which can then be accessed by props.singleCount
(line 5).
Destructuring props
with toRefs()
Alternatively, the toRefs()
helper function can be used to destructure props
without loosing reactivity:
<script setup lang="ts">
import { computed, toRefs } from 'vue';
const props = defineProps<{ singleCount: number }>();
const { singleCount } = toRefs(props);
const exponentialCount = computed(() => singleCount.value ** 2);
</script>
<template>
<div>
Exonential count: {{ exponentialCount }}
</div>
</template>
The toRefs()
function converts the reactive object props
into a plain object, whereby each of its properties is ref
pointing to the corresponding property of the original reactive object (documentation .
Summary
Starting from Vue 3.5.0, destructuring props
no longer breaks reactivity, making it easier to work with props in a clean and concise way. In versions below 3.5.0, it is still necessary to destructure props
with toRefs()
or by accessing it via the props object, to keep reactivity. This guide demonstrated both approaches using a simple counter example.