Vuex& VueJS(不要在突变处理程序之外改变vuex存储状态)

时间:2016-07-14 03:40:54

标签: javascript firebase vue.js firebase-authentication vuex

我试图创建一个 listenAuth 函数来监视" onAuthStateChanged "在 firebase 中,在用户登录或注销时通知 vuex商店。据我所知,我只是使用变异处理程序修改state.authData,除非我遗漏了什么?

我收到了错误:

[vuex] Do not mutate vuex store state outside mutation handlers.

这是我的App.vue javascript(来自我的组件)

<script>
// import Navigation from './components/Navigation'
import * as actions from './vuex/actions'
import store from './vuex/store'
import firebase from 'firebase/app'

export default {
  store,
  ready: function () {
    this.listenAuth()
  },
  vuex: {
    actions,
    getters: {
      authData: state => state.authData,
      user: state => state.user
    }
  },
  components: {
    // Navigation
  },
  watch: {
    authData (val) {
      if (!val) {
        this.redirectLogin
        this.$route.router.go('/login')
      }
    }
  },
  methods: {
    listenAuth: function () {
      firebase.auth().onAuthStateChanged((authData) => {
        this.changeAuth(authData)
      })
    }
  }
}
</script>

这是我的行动(changeAuth)功能

export const changeAuth = ({ dispatch, state }, authData) => {
  dispatch(types.AUTH_CHANGED, authData)
}

这是我的商店(重要的部分)

const mutations = {
  AUTH_CHANGED (state, authData) {
    state.authData = authData
  }
}

const state = {
  authData: {}
}

5 个答案:

答案 0 :(得分:10)

我也遇到过这个问题。我的商店:

  state: {
    items: []
  },
  mutations: {
    SetItems (state, payload) {
      // Warning
      state.items = payload.items
    }
  },
  actions: {
    FetchItems ({commit, state}, payload) {
      api.getItemsData(payload.sheetID)
        .then(items => commit('SetItems', {items}))
    }
  }

通过将state.items = payload.items替换为:

来修复它
state.items = payload.items.slice()
  

原因是数组在Javascript中存储为引用,payload.items可能会在Vuex之外更改。所以我们应该   只需使用payload.items的新副本。

对于州对象,请使用:

state.someObj = Object.assign({}, payload.someObj)

并且不要使用JSON.parse(JSON.stringify(someObj)),因为它要慢得多。

答案 1 :(得分:4)

在遇到同样的问题之后,我发现错误只发生在我们尝试将auth / user数据存储在Vuex状态时。

从......改变

const mutations = {
  AUTH_CHANGED (state, authData) {
    state.authData = authData
  }
}

...到...

const mutations = {
  AUTH_CHANGED (state, authData) {
    state.authData = JSON.parse(JSON.stringify(authData))
  }
}

会解决你的问题。

答案 2 :(得分:0)

我也遇到了这个问题,我用lodash克隆数据

state.someStatehere = $lodash.cloneDeep(data)

答案 3 :(得分:0)

对于任何也为此感到挣扎的人,这是解决它的另一种方法(对我实际有用):

auth()
  .onAuthStateChanged((user) => {
    if (user) {
      commit(MUTATION_TYPES.SET_USER, { ...user.toJSON() });
    }
  })

答案 4 :(得分:0)

所以从许多答案中我们可以就原因达成一致:存储在状态中的对象被持有对它的引用的东西默默地修改。许多人建议制作对象的副本。

另一种选择是在修改对象时清空状态。当由于某种原因您无法复制对象时,这会起作用。 例如:

bla({ state } {}) {
  mutatingMethod(state.xxx);
},

如果您知道 mutatingMethod 正在修改 xxx,那么您可以执行以下操作:

bla({ state } {}) {
  let xxx = state.xxx
  commit("SET_XXX", null)
  mutatingMethod(xxx);
  commit("SET_XXX", xxx)
},