Reputation: 125
I created a Snackbar component using vuetify components and imported that snackbar component to some other component. I am sending props from parent to child snackbar component. The snackbar closes automatically after some time. At this point error is coming like "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".
The snackbar closes automatically after 3 seconds. How to set state false after closing of snackbar.
Snackbar component
<v-snackbar
:timeout="timeout"
:color="color"
:top="y === 'top'"
:bottom="y === 'bottom'"
:right="x === 'right'"
:left="x === 'left'"
:multi-line="mode === 'multi-line'"
:vertical="mode === 'vertical'"
v-model="snackbar"
>
{{ text }}
<v-btn flat color="pink" @click.native="snackbarClose"><v-icon>{{close}}</v-icon></v-btn>
</v-snackbar>
props
props: ["snackbar", "y", "x", "mode", "timeout", "color", "close", "text", "submit"],
methods in snackbar component
methods: {
snackbarClose () {
this.$store.commit("snackbarClose", false)
// this.$emit('snackbarClose', false)
}
}
Parent component
<Snackbar
:close="close"
:snackbar="snackbarBox"
:y="y"
:x="x"
:mode="mode"
:timeout="timeout"
:color="snackbarColor"
:text="snackbarText"
:submit="text"
/>
data in parent component
data(){
return{
y: "top",
x: "right",
mode: "multi-line",
timeout: 3000,
text: "",
color: "",
close: "close",
}
}
importing getters in parent component
...mapGetters([ "snackbarBox"])
vuex mutations
snackbarClose: (state, payload) => {
state.snackbarBox = payload
},
state
snackbarBox: false,
getters
snackbarBox: state => {
return state.snackbarBox;
},
How to resolve this?
Upvotes: 1
Views: 2029
Reputation: 11
I had the same problem preparing a Snackbar component and I used a watcher to change the $state before "timeout" finished. By default, after 6 seconds the snackbar closes but I am using setTimeout with 4 second to modify the State and close it before this 6 seconds. In my case I am using ts but I think you can use it.
<template>
<div>
<v-snackbar v-model="snackbarData.show" :color="snackbarData.color" bottom >
{{snackbarData.message}}
</v-snackbar>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { Watch, Prop } from "vue-property-decorator";
@Component({})
export default class SnackBar extends Vue {
@Prop({default:null})
snackbarData!: Object
@Watch("snackbarData.show", { deep: true })
onShowChanges(value: any) {
if (value === true) {
const snackbar: any = {
show: false,
message:'',
color: null,
};
setTimeout( () => {
this.$store.commit('updateMainSnackbar', snackbar);
}, 4000)
}
}
}
This is my object but if you need more properties you should add them.
mainSnackbar: {
show: false,
message: '',
color: null
}
updateMainSnackbar (state:any, data: any){
state.mainSnackbar.show = data.show;
state.mainSnackbar.message = data.message;
state.mainSnackbar.color = data.color;
}
Import the component and pass the properties
<template>
<SnackBar :snackbarData="mainSnackbar" />
</template>
// ----------
<script lang="ts">
import Vue from "vue";
import { Component } from "vue-property-decorator";
import SnackBar from "SnackBar.vue"
@Component({
components: { SnackBar }
})
export default class OurComponent extends Vue {
// Computed
get mainSnackbar(){
return this.$store.state.mainSnackbar;
}
Call the mutation with the data you want to show in the snackbar. In my case I was using a method.
setSnackBar(){
const data= {
show: true,
message:'The message you want to show',
color: '#ffff',
};
this.$store.commit('updateMainSnackbar', data);
}
I hope it can help you.
Upvotes: 1
Reputation: 22403
Can you watch snackbar
in Snackbar component
?
something like:
watch: {
snackbar: function(newVal) {
if (!newVal) {
this.snackbarClose()
}
}
}
Upvotes: -1