Destructuring Vue.js props: The Reactivity Challenge
Tags: vue, javascript, frontend
Published: 2024-03-25 18:36:06

_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](https://vuejs.org/guide/extras/reactivity-transform#reactive-props-destructure)

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.

```html
<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](https://vuejs.org/api/composition-api-setup.html#accessing-props)

```html
<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()`:
```html
<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.

```html
<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._