簡體   English   中英

Vuex 和 VueJS(不要在變異處理程序之外改變 vuex 存儲狀態)

[英]Vuex & VueJS (Do not mutate vuex store state outside mutation handlers)

我試圖創建一個listenAuth功能手表火力“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: {}
}

我也遇到過這個問題。 我的店鋪:

  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修復它:

state.items = payload.items.slice()

其原因是,數組存儲在Javascript和引用payload.items可能Vuex外面改變。 所以我們應該只使用payload.items的新副本。

對於狀態對象,請使用:

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

並且不要使用JSON.parse(JSON.stringify(someObj))因為它要慢得多。

在為同樣的問題苦苦掙扎后,我發現只有當我們嘗試將 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))
  }
}

會解決你的情況。

我也有這個問題,我用 lodash 來克隆數據

state.someStatehere = $lodash.cloneDeep(data)

對於任何也在為此苦苦掙扎的人,這是另一種解決方法(實際上對我有用):

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

因此,從許多答案中我們可以就原因達成一致:存儲在狀態中的對象被持有對它的引用的某些東西默默地修改。 許多人建議制作對象的副本。

另一種選擇是在修改對象時清空狀態。 當由於某種原因您無法復制對象時,這會起作用。 例如:

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

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM