In Vue 3’s Composition API, most of your component’s logic goes into the setup() function.It receives props as its first argument, which is a reactive object. 

But a common pitfall for new users is that if you directly destructure props inside setup(), the destructured variables will lose their reactivity. This means they won’t update when the parent component changes the prop’s value.

Understanding the Reactivity Loss

When you receive props in setup(), Vue gives it as a reactive Proxy object. This Proxy is how Vue tracks changes to the props.

If you do this:

// Inside setup()const { myProp } = props;

Destructuring myProp in setup() breaks its reactivity. It becomes a plain value, so updates from the parent won’t change it or trigger re-renders in your component.

Also Read: How to Listen for ‘Props’ Changes

How to Maintain Reactivity of Props in setup()?

There are a few key ways to ensure your props remain reactive within setup():

1. Access Props Directly from the props Object

This is the simplest way. Just refer to the prop as props.propName everywhere you need it.

// ChildComponent.vue<script setup>

import { defineProps } from ‘vue’;

 

const props = defineProps([‘title’]);

</script>

 

<template>

  <h1>{{ props.title }}</h1> </template>

2. Use toRefs() for Destructured Props

If you want to destructure props but keep them reactive, wrap them with toRefs(). This converts each prop into a separate ref.

// ChildComponent.vue<script setup>

import { defineProps, toRefs } from ‘vue’;

 

const props = defineProps([‘message’]);

const { message } = toRefs(props); // ‘message’ is now a reactive ref

</script>

 

<template>

  <p>{{ message }}</p> 

</template>

Also Read: Why Enterprises are Choosing Vue.js for their Large-Scale Projects?

3. Use toRef() for a Single Prop

If you only need one specific prop as a reactive ref, toRef() is a concise option.

// ChildComponent.vue<script setup>

import { defineProps, toRef } from ‘vue’;

 

const props = defineProps([‘title’]);

const title = toRef(props, ‘title’); // ‘title’ is a reactive ref

</script>

 

<template>

  <h1>{{ title }}</h1> </template>

4. Use a computed Property for Derived Values

If you need to calculate or transform a prop, wrap the logic in a computed so it stays reactive.

// ChildComponent.vue<script setup>

import { defineProps, computed } from ‘vue’;

 

const props = defineProps([‘price’, ‘quantity’]);

 

const totalPrice = computed(() => props.price * props.quantity); // Reactive!

</script>

 

<template>

  <p>Total: {{ totalPrice }}</p> </template>

Key Takeaway

If you destructure props directly in setup(), they lose reactivity. To keep them reactive, use props directly, wrap them with toRefs() or toRef(), or use a computed for derived values. This way your component will update correctly when props change.

Related Resources