Skip to content
Advertisement

VueJS nested component doesn’t update property on action

This example of the official guide works properly (of course).

Then I tried by my own by making it a component, it also works.

But once nested in a parent component, the message can not be reversed, and I can’t figure out why.

Vue.component('todo-item', {
  props: ['todo'],
  template: '<div>' +
            '<li>{{ todo.text }}</li>' +
            '<button v-on:click="reverseMessage">Reverse Message</button>' +
            '</div>',
  methods: {
  reverseMessage: function () {
    var reversed = this.todo.text.split('').reverse().join('');
    console.log('tried with ' + reversed);
    this.todo.text = reversed;
  }
 }
});

Here is the JSFiddle : https://jsfiddle.net/37y1ukjh/

Advertisement

Answer

Look at this fiddle.

This is because of one-way data flow. You shouldn’t attempt to modify a prop’s value.

All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around. This prevents child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to reason about.

Couple options:
Define a local data property that uses the prop’s initial value as its initial and use that local property

value:
props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

Define a computed property that is computed from the prop’s value and use that computed property

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

Another option is to use an event to fire a parent method to change the prop but doesn’t seem to be necessary in this instance.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement