2

Suppose in a vue 3 component I have the following

<script>
export default {
  props: {
    minimumDays: Number
  },
  data() {
      return {
        days: this.minimumDays + Math.ceil(Math.random() * 40)
      }
  },
  methods: {
    increaseDays() {
      this.days = this.days + 1
    }
  }
}
</script>

As you can see I am using the value of a prop to compute the initial value of a mutable 'data' variable called "days." I was first trying to use the computed object to do this but received an error indicating that computed data should not be mutated.

Is this acceptable, to reference a prop in the establishment of data? Is there a correct technique for taking a bit of data from a prop, and using it, once modified, to establish mutable state in a component?

WillD
  • 5,170
  • 6
  • 27
  • 56

1 Answers1

1

It's ok if you're aware that changes in the prop won't be reflected in the child. That includes if the prop data is async and/or isn't defined when the child component is created. Doing it this way means copying the prop once prior to the creation of the child component.

If that's not what you want, then you could use a computed along with a mutable data property:

props: {
  minimumDays: Number
},
data() {
  return {
    adjustableDays: Math.ceil(Math.random() * 40)
  }
},
computed: {
  days() {
    return this.minimumDays + this.adjustableDays;
  }
},
methods: {
  increaseDays() {
    this.adjustableDays = this.adjustableDays + 1
  }
}

Here's a demo:

Vue.component('child', { 
  template: `
  <div>
    Adjustable: {{ adjustableDays }}<br>
    Total: {{ days }}<br>
    <button @click="increaseDays">Increase Adjustable (in Child)</button>
  </div>
  `,
  props: {
    minimumDays: Number
  },
  data() {
    return {
      adjustableDays: Math.ceil(Math.random() * 40)
    }
  },
  computed: {
    days() {
      return this.minimumDays + this.adjustableDays;
    }
  },
  methods: {
    increaseDays() {
      this.adjustableDays = this.adjustableDays + 1
    }
  }
})

new Vue({
  el: "#app",
  data() {
    return {
      min: 15
    }
  }
});
<div id="app">
  Minimum: {{ min }}
  <child :minimum-days="min"></child>
  <button @click="min++">Increase Minimum (in Parent)</button>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
Dan
  • 59,490
  • 13
  • 101
  • 110