我试图创建一个 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: {}
}
答案 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)
},