1
votes

I'm facing a weird issue with my Electron + Vue setup.

CONDITIONS: Electron + Vue (I used a boilerplate) + vuex-persist (also tried vuex-persistedstate and vuex-persistfile).

PROBLEM: Vuex getters remain 0/null/'' when the store is being rehydrated. How do I know that? If the local storage is clean (I launch the app for the first time), first mutations update state (getters return correct values) and I can see an object being added to the browser's local storage. When the app is restarted, however, mutations trigger state and local storage update just like before, BUT getters remain empty/default. Below getter returns an empty array.

enter image description here

SETUP: I have an app that works with 3rd party API: gets data, calculates stuff and sends some data back. API also requires authorization. Below is my Vuex structure.

Part of my state object...

const state = {
  token: '',
  projects: [],
  work_packages: [],
  timeEntriesLocal: []
}

...and one of my getters:

const getters = {
  todayLog () {
    function sameDay (d1, d2) {
      return d1.getFullYear() === d2.getFullYear() &&
        d1.getMonth() === d2.getMonth() &&
        d1.getDate() === d2.getDate()
    }
    var entries = state.timeEntriesLocal
    var todayEntries = []
    entries.forEach(element => {
      var date = element.spentOn
      var today = new Date()
      if (sameDay(date, today)) {
        todayEntries.push(element)
      }
    })
    return todayEntries
  }
}

It returns entries from an array that are due to "today".

timeEntriesLocal is filled with this method:

addTimeEntry () {
  let entry = {
    id: this.$store.state.UserData.timeEntriesLocal.length + 1,
    project: this.getItemById(this.$store.state.UserData.current.project_id, this.$store.state.UserData.projects),
    spentOn: new Date(),
    comment: this.comment,
    activityId: this.activityId,
    workPackage: this.getItemById(this.$store.state.UserData.current.work_package_id, this.$store.state.UserData.work_packages),
    hours: this.precisionRound(this.$store.state.UserData.duration / 60 / 60, 2),
    published: false,
    loading: false,
    infoMessage: ''
  }

  this.$store.commit('ADD_LOCAL_ENTRY', entry)
}

And lastly here's the mutation that I have just used above:

ADD_LOCAL_ENTRY (state, entry) {
  state.timeEntriesLocal.unshift(entry)
}
1

1 Answers

0
votes

The changes in timeEntriesLocal are not being picked up, since you're changing the length of the Array. This is a limitation of JavaScript covered in Common Gotchas section of the docs. A way to go around it is also covered in Vuex`s docs:

Mutations Follow Vue's Reactivity Rules

Since a Vuex store's state is made reactive by Vue, when we mutate the state, Vue components observing the state will update automatically. This also means Vuex mutations are subject to the same reactivity caveats when working with plain Vue:

  1. Prefer initializing your store's initial state with all desired fields upfront.
  2. When adding new properties to an Object, you should either:

    • Use Vue.set(obj, 'newProp', 123), or
    • Replace that Object with a fresh one. For example, using the object spread syntax we can write it like this: state.obj = { ...state.obj, newProp: 123 }

So in your exmample, to make the Vue (Vuex) detect these changes, you can do something like:

ADD_LOCAL_ENTRY (state, entry) {
    state.timeEntriesLocal.unshift(entry);
    Vue.set(state, 'timeEntriesLocal', state.timeEntriesLocal);
}