1

I'm trying to build an Electron app with VueJS using the electron-vue boilerplate. I have a mutation which updates parts of the state based on the payload it receives.

However, somewhere between the action call and the mutation, the property payload.myItem.id changes without any intention. The action is called by a Vue modal component:

    handleModalSave() {
      let payload = {
        layerId: this.layer.id,
        myItem: {
          id: this.editLayerForm.id,
          text: this.editLayerForm.text
        }
      }
      console.log('save', payload.myItem.id)
      this.$store.dispatch('addLayerItem', payload)
    }

Here are said action and mutation:

  // Action
  addLayerItem: ({ commit }, payload) => {
    commit('ADD_LAYER_ITEM', payload)
  }

  // Mutation
  ADD_LAYER_ITEM: (state, payload) => {
    console.log('mutation', payload.myItem.id)
    let layer = state.map.layers.find(layer => layer.id === payload.layerId)

    if (payload.myItem.id !== '') {
      // Existing item
      let itemIdx = layer.items.findIndex(item => item.id === payload.myItem.id)
      Vue.set(layer.items, itemIdx, payload.myItem)
    } else {
      // New item
      payload.myItem.id = state.cnt
      layer.items.push(payload.myItem)
    }
  }

Here is a screenshot of the console logs:
console screenshot

As far as I can see, there is no command to change myItem.id between console.log('save', payload) and console.log('mutation', payload). I use strict mode, so there is no other function changing the value outside of the mutation.

Edit
I updated the console.logs() to display the property directly instead of the object reference.

Community
  • 1
  • 1

2 Answers2

0

As far as I can see, there is no command to change myItem.id between console.log('save', payload) and console.log('mutation', payload).

It doesn't need to change between the console logging.

In the pictures you've posted you'll see a small, blue i icon next to the console logging. If you hover over that you'll get an explanation that the values shown have just been evaluated.

When you log an object to the console it grabs a reference to that object. It doesn't take a copy. There are several reasons why taking a copy is not practical so it doesn't even try.

When you expand that object by clicking in the console it grabs the contents of its properties at the moment you click. This may well differ from the values they had when the object was logged.

If you want to know the value at the moment it was logged then you could use JSON.stringify to convert the object into a string. However that assumes it can be converted safely to JSON, which is not universally true.

Another approach is to change the logging to directly target the property you care about. console.log(payload.myItem.id). That will avoid the problem of the logging being live by logging just the string/number, which will be immutable.

The line that changes the id appears to be:

payload.myItem.id = state.cnt

As already discussed, it is irrelevant that this occurs after the logging. The console hasn't yet grabbed the value of the property. It only has a reference to the payload object.

The only mystery for me is that the two objects you've logged to the console aren't both updated to reflect the new id. In the code they appear to be the same object so I would expect them to be identical by the time you expand them. Further, one of the objects shows evidence of reactive getters and setters whereas the other does not. I could speculate about why that might be but most likely it is caused by code that hasn't been provided.

I use strict mode, so there is no other function changing the value outside of the mutation.

Strict mode only applies to changing properties within store state. The object being considered here is not being held in store state until after the mutation. So if something were to change the id before the mutation runs it wouldn't trigger a warning about strict mode.

skirtle
  • 27,868
  • 4
  • 42
  • 57
  • Thanks for your answer, really appreciated! I updated the logs to display the property `payload.myItem.id` and it still shows the value in the logs before it is assigned in the mutation. This is really frustrating because I can't identify new items that should come without an ID assigned. Is there any code that you need to see in particular in order to inspect the problem further? I included the action as well since this should be the only code part that is being called between the $emit and the mutation, right? – user2307798 Nov 27 '19 at 07:57
  • @user2307798 Try putting some logging at the start of the action to check if the `id` is correct at that point. I notice you aren't using namespacing. Is it possible that you have an `addLayerItem` action or an `ADD_LAYER_ITEM` mutation is a different module? If you do then they will also be called. The final thing to try is adding a `debugger` statement just before you call `dispatch`. You might have to step into some code you don't really understand but it should be pretty obvious whether a line might change the `id` or not. – skirtle Nov 27 '19 at 08:26
  • I added a `console.log('action', payload.myItem.id)` to the action, can't see the actual log in the DevTools console. However, I can see the log in the Terminal. If you don't know Electron, you start your app in the Terminal and there are logs going to the Terminal as well. I used the vue-electron boilerplate which is linked in first sentence. To answer your other question, this is the only action/mutation called `addLayerItem` in all my store modules. Do you have any details about how to include debugger statements? – user2307798 Nov 27 '19 at 09:09
  • @user2307798 You mention that you could see the logging in the Terminal but you didn't mention what value you saw. Regarding debugger statements, you just write the word `debugger` on a line by itself and it will cause execution to stop on that line, just like a breakpoint. You can then step through line by line. I am not familiar with Electron so I don't know whether that has a built in debugger. If not you may need to connect a remote debugger. – skirtle Nov 27 '19 at 09:22
  • It shows the correct value (empty string) in the terminal. What's weird is that, in the terminal, the 'mutation' log also shows the correct value (empty string). It's the DevTools console and Vue DevTools that show wrong values. I also used the debugger and at some point, it got stuck in a function called `handleMessage(event)` in client.js. – user2307798 Nov 27 '19 at 09:53
0

Okay I found the root cause for my issue. Vuex was configured to use the createPersistedState plugin which stores data in local storage. Somehow, there was an issue with that and data got mixed up between actual store and local storage. Adding a simple window.localStorage.clear() in main.js solved the problem!