10

我正在尝试创建一个listenerAuth函数,该函数在 firebase 中监视“ onAuthStateChanged ,以在用户登录或退出时通知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: {}
}
4

5 回答 5

19

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

  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)),因为它要慢得多。

于 2017-05-19T18:01:31.137 回答
11

在解决了同样的问题后,我发现只有当我们尝试将 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))
  }
}

会解决你的情况。

于 2017-05-18T14:54:50.433 回答
0

我也有这个问题,我用lodash克隆数据

state.someStatehere = $lodash.cloneDeep(data)
于 2019-07-04T09:12:22.593 回答
0

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

另一种选择是在修改对象时清空状态。当由于某种原因您无法复制对象时,此方法有效。例如:

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

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

bla({ state } {}) {
  let xxx = state.xxx
  commit("SET_XXX", null)
  mutatingMethod(xxx);
  commit("SET_XXX", xxx)
},
于 2021-07-08T04:56:47.577 回答
-1

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

auth()
  .onAuthStateChanged((user) => {
    if (user) {
      commit(MUTATION_TYPES.SET_USER, { ...user.toJSON() });
    }
  })
于 2020-08-13T22:29:24.707 回答