Reputation: 13
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>
Upvotes: 1
Views: 5850
Reputation: 2355
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>
Upvotes: 1
Reputation: 1731
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.
Upvotes: 1