Vuex - 'не изменять состояние хранилища vuex вне обработчиков мутаций' - PullRequest
2 голосов
/ 07 мая 2019

Я пытаюсь инициализировать мой магазин Vuex из Firestore. Последняя строка кода context.commit('SET_ACTIVITIES', acts) - это то, что создает ошибку. Я не думаю, что я мутирую напрямую, так как использую действие. Чего мне не хватать?

Вот мой магазин Vuex:

export default new Vuex.Store({
  strict: true,
  state: {
    activities: []
  },
  mutations: {
    SET_ACTIVITIES: (state, activities) => {
      state.activities = activities
    },
  },

  actions: {
    fetchActivities: context => {
      let acts = []
      let ref = db.collection('activities')
      ref.onSnapshot(snapshot => {
        snapshot.docChanges().forEach(change => {
          if(change.type == 'added') {
            acts.push({
              id: change.doc.id,
              name: change.doc.data().name,
              day: change.doc.data().day
            })
          }
        })
      })
      context.commit('SET_ACTIVITIES', acts)
    }
  }

Также выдает ошибку, равную количеству предметов в Firestore. Зачем это делать, если я делаю только один коммит?

Консоль

[Vue warn]: ошибка в обратном вызове для наблюдателя "function () {return this._data. $$ state}": "Ошибка: [vuex] не изменяет состояние хранилища vuex вне обработчиков мутаций."

и

Error: [vuex] do not mutate vuex store state outside mutation handlers.
    at assert (vuex.esm.js?2f62:87)
    at Vue.store._vm.$watch.deep (vuex.esm.js?2f62:763)
    at Watcher.run (vue.runtime.esm.js?2b0e:4562)
    at Watcher.update (vue.runtime.esm.js?2b0e:4536)
    at Dep.notify (vue.runtime.esm.js?2b0e:730)
    at Array.mutator (vue.runtime.esm.js?2b0e:882)
    at eval (store.js?c0d6:36)
    at eval (index.cjs.js?e89a:21411)
    at eval (index.cjs.js?e89a:4904)
    at LLRBNode.inorderTraversal (index.cjs.js?e89a:1899)

1 Ответ

2 голосов
/ 07 мая 2019

Вы столкнулись с проблемой со ссылками на объекты и асинхронными методами.

CollectionReference#onSnapshot() работает асинхронно, вызывая прослушиватель / наблюдатель моментального снимка при QuerySnapshot событиях.

В основном, что происходит в вашем коде, это то, что вы присваиваете пустой массив acts для state.activities (та же ссылка на объект) в вашей мутации, а затем, позже, в вашем обработчике событий snapshot ,непосредственно вставьте в него элементы.

Быстрое решение состояло бы в том, чтобы зафиксировать мутацию в onSnapshot наблюдателе

fetchActivities: context => {
  let ref = db.collection('activities')
  ref.onSnapshot(snapshot => {
    let acts = []
    snapshot.docChanges().forEach(change => {
      if(change.type == 'added') {
        acts.push({
          id: change.doc.id,
          name: change.doc.data().name,
          day: change.doc.data().day
        })
      }
    })
    context.commit('SET_ACTIVITIES', acts)
  })
}

Если вы хотите только произвести первоначальную выборку вашегоДля сбора данных используйте CollectionReference#get().Если он возвращает обещание, вы можете использовать его, чтобы сделать ваше действие составным

async fetchActivities ({ commit }) {
  let snapshot = await db.collection('activities').get()
  let acts = snapshot.docChanges().filter(({ type }) => type === 'added')
      .map(({ doc }) => ({
        id: doc.id,
        name: doc.data().name,
        day: doc.data().day
      }))
  commit('SET_ACTIVITIES', acts)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...