Search code examples
javascriptvue.jsvuejs2vuexnuxt.js

Vuex - Do not mutate vuex store state outside mutation handlers. State changed inside mutation


I'm calling a store action from the main layout (nuxt.js default.vue) I'm then calling a state mutation within the mutations export. Why am I getting this error?

Error in console: http://prntscr.com/rwvfjf

Code:

default.vue

created () {
  this.$store.dispatch("update_user");
  ...
}

Store (store/index.js)

export const state = {
  ...
  state: null, 
}

export const actions {
  ...
  update_user({commit}) {commit("update_user")}
}

export const mutations = {
  async update_user(state) {
    if (state.token == undefined) {
      return
    }
    if (this.$axios.defaults.headers.common["authorization"] == undefined) {
      this.$axios.defaults.headers.common["authorization"] = state.token
    }
    var user = await this.$axios.get("/api/v1/user/@me");
    state.user = user;
  },
}


Solution

  • From the docs:

    Mutations Must Be Synchronous

    One important rule to remember is that mutation handler functions must be synchronous

    It looks like you have them reversed. Restructure your action and mutation to:

    Action

    export const actions = {  // <-- was missing an equals
      ...
      async update_user({ state, commit }) { // <-- state and commit needed
        if (state.token == undefined) {
          return
        }
        if (this.$axios.defaults.headers.common["authorization"] == undefined) {
          this.$axios.defaults.headers.common["authorization"] = state.token
        }
        var user = await this.$axios.get("/api/v1/user/@me");
        commit("update_user", user); // <-- Passing the user data to the mutation
      }
    }
    

    Mutation

    export const mutations = {
      update_user(state, user) {
        state.user = user;
      },
    }
    

    Also notice, the async action returns data that is then passed to the mutation, where it's set to state. You may have an error with this.$axios too, once that's fixed. If so, make sure you're importing it:

    import axios from 'axios';
    

    and using it like:

    if (axios.defaults.headers.common["authorization"] == undefined) {
      axios.defaults.headers.common["authorization"] = state.token
    }