Vuex: Certain store mutations do not trigger updates

Created on 23 Feb 2017  路  11Comments  路  Source: vuejs/vuex

Hi there,

I have a pretty basic Vue+Vuex setup.
Let A be a component with a computed field which depends on the Vuex store and a lifecycle hook --- created() which dispatches an event to the store to request some data from a RESTful server.

The expected behavior and a deviation from it are as follows:

  1. created() dispatches an event to the store; goes well
  2. the store makes requests and commits data; goes well
  3. mutation updates the state; goes well (this can be seen in the developers tab of Vue in Chrome)
  4. computed field is updated triggering a re-render of the template; it depends

The last procedure goes well, i.e., the component template is re-rendered after the updates, if the field of the store being updated is an array and this array is updated with methods like push(), splice() (may be others too, but I did not investigate further).

The last procedure does not go well, if the field of the store being updated is an array and this array is updated via index access, e.g., array[n] = data. Or if the field is an object.

I made a repository containing this example.
It contains a restful server which gives out some data and the Vue+Vuex setup I described. There in file store.ts I present two described options --- with the array and object --- they are marked with !!! in the beginnings of commented line.

By default the array option is active, so everything must update as expected. If you uncomment lines related to the object and comment those related to the array, no update of the component template will happen.

documentation

Most helpful comment

@quicky84 Vue.set(object, key, data).

Objects: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
Arrays: https://vuejs.org/v2/guide/list.html#Caveats

Closing, as this is not a bug.

All 11 comments

You should use: array.splice(n, 1, data)

All right. I figured it out. But how do you go about objects? Object are musch handier if you update data in the store. Setting fileds as object[key] = data does not trigger updates either.

PS: I did not find docs that arrays must be modified with splice to trigger changes.

@quicky84 Vue.set(object, key, data).

Objects: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
Arrays: https://vuejs.org/v2/guide/list.html#Caveats

Closing, as this is not a bug.

IMO https://vuex.vuejs.org/en/mutations.html should have examples or more info this.

@znck well, there is a note, https://vuex.vuejs.org/en/mutations.html#mutations-follow-vues-reactivity-rules
Maybe bringing it up a few sections will help?

Reopening to track docs.

Thanks a lot for pointing to the right piece of docs. I must have been too anxious to jump into action.

Hi all,

Seems the doc is missing the case when updating a value in an array.

Here is a thread on the topic: https://forum-archive.vuejs.org/topic/2243/updating-an-object-in-array-inside-vuex-store-doesn-t-result-in-view-update

I am not sure what is the doc status at this stage. Should I update it ?

I'm having this same issue, but NOT with an array.

I'm updating a single, numeric, value.


I have steps and stepsComplete. These are mutated in rapid succession during route changes. They are accessed through getters from the component.

I can follow, in the devtools, each commit and store state. But they are not always represented on the component:

  • Starting with: steps: 2 stepsComplete: 2
  • In every step, the vuex state matches what is expected. I recorded this via the devtools and vuex "time travel"
  1. Set steps = 1, stepsComplete = 0

    • Component shows: steps: 1 stepsComplete: 2 :x:

  2. Set steps = 2

    • Component shows: steps: 2 stepsComplete: 2 :x:

  3. Set stepsComplete = 1

    • Component shows: steps: 2 stepsComplete: 1 :heavy_check_mark:

  4. Set stepsComplete = 2

    • Component shows: steps: 2 stepsComplete: 2 :heavy_check_mark:

As you can imagine having a loading bar going from 0 to 100%, then to 50%, then to 100% is a bit concerning, especially when the Vuex state matches, but the component doesn't always match.

@quicky84 Vue.set(object, key, data).

Objects: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
Arrays: https://vuejs.org/v2/guide/list.html#Caveats

Closing, as this is not a bug.

Hey @simplesmiler but how can we cannot use $set in vuex mutations ?
I am facing a similar issue, adding a new key to an object in store
In case of array my computed property in component gets updated but doesn't work when setting the value as a string.

@goelrohan6 When adding a new key to the object, and when you can't use Vue.set, you should recreate fresh one as described at the doc.

state.data = Object.assign({}, state.data, { a: 1, b: 2 })

/// or...

state.data = { ...state.data, a: 1, b: 2 }

And, I'll be closing this issue for now since it's quite outdated, and the discussion isn't matching the latest topics. Please feel free to open another issue if you find anything! 馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jbruni picture jbruni  路  3Comments

Nickvda picture Nickvda  路  3Comments

jdittrich picture jdittrich  路  3Comments

gongzza picture gongzza  路  3Comments

james-wasson picture james-wasson  路  3Comments