Destructuring Vue.js props: The Reactivity Challenge

Destructuring Vue.js props: The Reactivity Challenge

·

2 min read

Destructuring objects is a common practice in JavaScript, and it can make your code cleaner by extracting specific properties. In Vue.js, however, destructuring props can unintentionally break reactivity.


The Pitfalls of Destructured Props

⚡ You cannot destructure defineProps because the resulting destructured variables are not reactive and will not update. Read more

When you destructure props in Vue.js, the resulting variables become plain JavaScript objects. These objects are not reactive, meaning changes to the original props won't trigger a re-render in your component. This can lead to stale data being displayed.

For example, imagine a component displaying a firstName and a lastName based on a prop. If the prop is destructured, the properties won't update when the parent component changes the prop value.

<template>
  <div>
    <p>Name: {{ firstname }} {{ lastname }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// ❌ Non-reactive props - this won't re-render
const { firstName, lastName } = defineProps({
  firstName: String,
  lastName: String,
});
</script>

Keeping destructured props reactive (if necessary)

If you still really, really want to destructure props, there are two ways to maintain reactivity:

  • Reference your props object directly using toRefs() Vue’s toRefs function takes a reactive object (like props) and returns a new object where each property is wrapped in a ref. Accessing properties using .value (e.g., prop1.value) ensures reactivity.

⚡ Vue.js documentation advises against this approach for props, suggesting using the dot notation instead. Read more

<template>
  <div>
    <p>Name: {{ firstName }} {{ lastName }}</p>
  </div>
</template>

<script setup>
import { ref, toRefs } from 'vue';

const props = defineProps({
  firstName: String,
  lastName: String,
})

const { firstName, lastName } = toRefs(props)
</script>
  • Reference your props object directly using computed():
<template>
  <div>
    <p>{{ fullName }}</p>
  </div>
</template>

<script setup>
import { computed } from 'vue';
const { firstName, lastName } = defineProps({
  firstName: String,
  lastName: String
})
const fullName = computed(() => firstName + lastName)
</script>

The Bottom Line: Embrace the Dot Notation!

While destructuring can be useful for non-reactive objects, it’s generally recommended to access props directly using props.propertyName in Vue.js.

<template>
  <div>
    <p>Name: {{ props.firstname }} {{ props.lastname }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// ✅ Reactive props - this will re-render
const props = defineProps({
  firstName: String,
  lastName: String,
});
</script>

This approach guarantees reactivity and avoids potential issues.


Remember, young traveler, maintaining reactivity is crucial for dynamic Vue components. Choose the approach that suits your style, but be mindful of the potential pitfalls of destructuring props.

Did you find this article valuable?

Support richardev by becoming a sponsor. Any amount is appreciated!