Oscar Schafer
Oscar Schafer

Reputation: 1545

Why does a prop change not change data?

I'm trying to understand why changing a prop, used to provide an initial value, doesn't cause the data variable to change.

In the below example, changing the initialName value passed in the parent component, also causes the initialName to change in the child component. However, name keeps the value it was originally initialized as. I believed, seemingly incorrectly, that changing a prop would re-render the component.


ChildComponent.vue

<template>
    <div>
        {{initialName}}
        {{name}}
    </div>
</template>
<script>
export default {
    props: {
        initialName: {
            type: String,
            default: '',
        }
    },
    data() {
        return {
            name: this.initialName,
        };
    },
</script>


ParentComponent.vue

<template>
    <ChildComponent :initialName="AnExampleName"/>
</template>
<script>
import ChildComponent from ChildComponent.vue
export default {
    components: {
        ChildComponent
    }
</script>

I've been able to work around this by watching the prop and updating name, however this doesn't feel like the best approach.

How come changing the prop doesn't change the data? Is there a better way to pass an initial value to a child component?

Upvotes: 5

Views: 8379

Answers (2)

Norio De Sousa
Norio De Sousa

Reputation: 146

I just learned on Laracasts that you can use provide and inject instead.

In your parent component:

import { provide, ref } from 'vue';

const name = ref('John Doe');

setTimeout(() => {
  name.value = 'Jane';
}, 2000);

And in your child component:

import { inject } from vue;

let name = inject('name');

You don't need to add it in props and any changes to name will reflect in both your parent and your child.

This works from your parent down to all its children. (So it's not app-wide. For that, try Pinia / VueX.)

For more, here's Jeffrey's free lesson: https://laracasts.com/series/learn-vue-3-step-by-step/episodes/22

Upvotes: 0

kissu
kissu

Reputation: 46814

data is meant to be static, so if you set it once, it will not be reactive afterwards.
It will change if you mutate it directly of course, like this this.name = 'updated value hi hi'.
But it will not mutate if you update another prop/state elsewhere (like initialName in your example).

A simple approach for this would be to use a computed like this

<script>
export default {
  props: {
    initialName: {
      type: String,
      default: "",
    },
  },
  computed: {
    name() {
      return this.initialName
    }
  },
};
</script>

This example proves that the usage of data is NOT updating the name value (initialName is totally reactive) if you do use it like the OP did. The usage of computed solves this issue tho.

Upvotes: 6

Related Questions