Search code examples
vue.jsvuex

Error "Vuex do not mutate vuex store state outside mutation handlers" when no mutation outside vuex occurs


I have a mutation defined inside Vuex that looks like this:

setError(state, error) {
    state.error = error
    setTimeout(() => {
      state.error = null
    }, 5000)
  },

And I call it like this:

...
catch (error) {
          this.$store.commit('setError', error.response.data.error.message)
        }
...

When the timeout period expires, I get an error: [vuex] do not mutate vuex store state outside mutation handlers. I don't get it, because I'm not mutating anything outside of Vuex.

Can anyone suggest how to fix this?

I could fix this by simplifying setError to just assigning the error and dropping the setTimeout part, but I had to do this elsewhere like this:

flashError(message) {
      this.$store.commit('setError', message)
      setTimeout(() => {
        this.$store.commit('setError', null)
      }, 5000)
    },

This solution seems suboptimal because I want to be able to set this error temporarily everywhere

Many thanks


Solution

  • Based on our comment exchange, I created a sample component that demonstrates how to auto close a flash error without involving Vuex.

    <template>
      <div class="flash-error-auto-close">
        <h4>Flash Error with Auto Close</h4>
        <div class="row">
          <div class="col-md-6">
            <button class="btn btn-secondary" @click="triggerTimedErrorDisplay">Show Flash Error</button>
            <div id="flash-error" v-if="displayError" class="alert alert-danger" role="alert">
              {{ errorMessage }}
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            errorMessage: 'This is the error message',
            displayError: false,
            displayTime: 5000
          }
        },
        methods: {
          triggerTimedErrorDisplay() {
            this.displayError = true;
    
            setTimeout( () => {
              this.displayError = false;
            }, this.displayTime);
          }
        }
      }
    </script>
    
    <style scoped>
      #flash-error {
        margin-top: 0.5rem;
      }
    </style>