I have a snackbar from Vuetify. It's in default.vue
and the vuex
store controls the v-model
, message
and color
:
DefaultSnackBar.vue
<template>
<v-container>
<v-snackbar
v-model="snackbarProperties.show"
:color="snackbarProperties.color"
timeout="7000"
multi-line
>
{{ snackbarProperties.message }}
<template v-slot:action="{ attrs }">
<v-btn
text
v-bind="attrs"
@click="hideSnackbar"
>
Close
</v-btn>
</template>
</v-snackbar>
</v-container>
</template>
<script>
import { mapActions } from "vuex";
import { mapGetters } from "vuex";
export default {
methods :{
...mapActions("Snackbar",["showSnackbar","hideSnackbar"]),
},
computed: {
...mapGetters("Snackbar",["snackbarProperties"])
},
}
</script>
Snackbar.js
export const state = () => ({
message: "",
color: "",
show: false,
});
export const getters = {
snackbarProperties: state => {
return state;
},
}
export const mutations = {
showSnackbar: (state, payload) => {
state.message = payload.message;
state.color = payload.color;
state.show = true;
},
hideSnackbar: (state) => {
state.message = "";
state.color = ""
state.show = false;
},
}
export const actions = {
showSnackbar({ commit }, payload) {
commit('showSnackbar', payload)
},
hideSnackbar({ commit }) {
commit('hideSnackbar')
}
}
When I call showSnackbar({...})
the bar appears correctly with no errors, but when it disappears (timeout is reached) is get this error and everything crashes
do not mutate vuex store state outside mutation handlers
I think it's because when the bar disappears the component changes the value of the v-model
it's attached to but I'm not sure how to work around this.
I found the answer from this vue forum:
Use an action with the setTimeout code in it. Then in the timeout commit the mutation. Mutations should be synchronous which is why using a timeout in them is throwing a warning.
I've updated Snackbar.js
to suit:
export const state = () => ({
message: "",
color: "",
show: false,
});
export const getters = {
snackbarProperties: state => {
return state;
},
}
export const mutations = {
showSnackbar: (state, payload) => {
state.message = payload.message;
state.color = payload.color;
state.show = true;
},
hideSnackbar: (state) => {
state.message = "";
state.color = ""
state.show = false;
},
}
export const actions = {
showSnackbar({ commit }, payload) {
commit('showSnackbar', payload)
setTimeout(() => {
commit('hideSnackbar')
}, 500);
},
hideSnackbar({ commit }) {
commit('hideSnackbar')
}
}