0
votes

How to fix Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "show" problem?

my SnackbarComponent.vue:

<template>
  <v-snackbar
    v-model="show"
    :top="pinY === 'top'"
    :right="pinX === 'right'"
    :bottom="pinY === 'bottom'"
    :left="pinX === 'left'"
    :color="variant"
    :timeout="timeout"
    :vertical="mode === 'vertical'"
    :multi-line="mode === 'multi-line'"
  >
    {{ message }}
    <v-btn fab @click="show = false" color="transparent" depressed>
      close
    </v-btn>
  </v-snackbar>
</template>
<script>
export default {
  props: {
    show: {
      type: Boolean,
      required: true,
      default: false
    },
  },
  data() {
    return {

    }
  }
}
</script>
2

2 Answers

0
votes

The issue here is in the line below. A property should not be updated in the child component:

<v-btn fab @click="show = false" color="transparent" depressed> 

So what I suggest is to create a new variable by connecting it to the prop and do what ever we need after as below :

<template>
    <v-snackbar v-model="showModal"
                :top="pinY === 'top'"
                :right="pinX === 'right'"
                :bottom="pinY === 'bottom'"
                :left="pinX === 'left'"
                :color="variant"
                :timeout="timeout"
                :vertical="mode === 'vertical'"
                :multi-line="mode === 'multi-line'">
        {{ message }}
        <v-btn fab @click="hideModal" color="transparent" depressed>
            close
        </v-btn>
    </v-snackbar>
</template>
<script>
    export default {
        props: {
            show: {
                type: Boolean,
                required: true,
                default: false
            },
        },
        data() {
            return {
                showModal: this.show /*The local variable added and referred in v-snackbar */
            }
        },
        methods: {
            /*New method to hide the snackbar, you could still be using inline 
              coding and replace the prop by the new variable*/
            hideModal() {
                this.showModal = false;
            }
        }
    }
</script> 
0
votes

You cannot mutate a prop directly instead you can emit an event from child component & change the data property being passed as a prop to the child component as per requirement.

To read more: https://vegibit.com/vuejs-parent-child-communication/

Child.vue

<template>
  <v-snackbar
    v-model="show"
    :top="pinY === 'top'"
    :right="pinX === 'right'"
    :bottom="pinY === 'bottom'"
    :left="pinX === 'left'"
    :color="variant"
    :timeout="timeout"
    :vertical="mode === 'vertical'"
    :multi-line="mode === 'multi-line'"
  >
    {{ message }}
    <v-btn fab @click="handleClose" color="transparent" depressed>
      close
    </v-btn>
  </v-snackbar>
</template>

<script>
export default {
  props: {
    show: {
      type: Boolean,
      required: true,
      default: false
    },
  },
  data() {
    return {}
  },
  methods: {
   handleClose() {
    this.$emit('onClose')
   }
  }
}
</script>

Parent.vue

<template>
 <div>
  <Child 
   :show="show"
   @onClose="handleClose"
  />
 </div>
</template>

<script>
 import Child from './Child.vue'
 export default {
  data () {
   return {
    show: true
   }
  },
  components: {
   Child
  },
  methods: {
   handleClose () {
    this.show = false
   }
  }
 }
</script>

So, here child is emitting an event on the close button, on emit a handler fn in the parent is called where data property show in the parent is set to false. And, since the show is being passed as a prop to a child component, the child gets the updated value for prop show & update the component accordingly.