Vuex state not update unless set recording in Vue devtools


#1

HTML:

<div id="main">
  <input type='text' name='Added' v-model='controlValue' />
  <input type='button' value='Create' @click='createProperty' />
</div>
<script src='bundle.js'></script>

JS file before webpack processing:

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);
const v = new Vue({
    el: "#main",
    store: new Vuex.Store({
        state: { data: { } },
        mutations: {
            changeValue: function(state, payload) {
                state.data[payload.propertyName] = payload.value;
            },
        },
        actions: {
            changeValue: function(context, payload) {
                context.commit("changeValue", payload);
            },
        },
    }),
    computed: {
        controlValue: function() {
            return this.$store.state.data.Added;
        }
    },
    methods: {
        createProperty: function() {
            this.$store.dispatch(
                'changeValue',
                { propertyName: "Added", value: "Added!" });
        },
    },
});

So, the initial value of the text input is linked to an undefined field of the store state. After click the button, the specified field would be added to the Vuex store, so the text input should display its value (“Added!”).

But when I open this page in my Chrome and debug with devtools, I find the behavior of Vuex store depends on if I choose to record the mutations in Vue devtool. If I choose to record, after I select commit the mutation, the state will be updated and the input will display “Added!”. But if I choose not recording, nothing will happen, the state will stay the same (displaying: data:Object (empty)), the input will still be empty, click Refresh will not change anything.

Change “this.$store.dispatch” to “this.$store.commit” makes no difference.

Am I missing something?

Related versions:
Vue: 2.2.4
Vuex: 2.2.1
Chrome: 57.0.2987.110
Vue.js devtools: 3.1.2


#2

Hmmm. Silly me.

This might be related to:
"Mutations Follow Vue’s Reactivity Rules"
part of Vuex document.


#3

Yep. If attribute is undefined during initialization, it won’t be reactive. :slight_smile:


#4

Kangkai1980 - what was your solution? Because I also have troubles with the reactivity like you have… :frowning:

I have arrays of objects in the vuex store state, and I have som reactivity problems with them, when I add a new object to the array it is show, but when I update a property of that new object, all newly added objects in the array get their property updates with the same value?

I really need some great examples on how to work with dynamic (adding, removing, editing) arrays of objects in vuex. I have read all the reactivity rules on arrays and objects on https://vuejs.org/ but still no luck…


#5

Well. I have same issue, too.

I have tested with state type as string, array, object, but have got same issue.

Nobody knows the solution??

main.js

          mounted() {
        this.$nextTick(function () {
          this.init()
        })
      },
      methods: {
        init: () => {
          store.dispatch('setArtists')
        }
      }

store.js

     mutations: {
    addArtist(state, payload) {
      this.state.artists[payload.id] = payload.data
    }
  },
  getters: {
    artists: state => {
      return Object.keys(state.artists).map((key,index) => {
        return {
          id: key,
          name: state.artists[key].name,
          biography: state.artists[key].biography
        }
      })
    }
  },
  actions: {
    setArtists ({commit, state}) {
      const firestore = FirebaseApp.firestore()
      const settings = {  timestampsInSnapshots: true }
      firestore.settings(settings)
      const collection = firestore.collection('artists').where('status', '==', 'active')

      collection.get().then(snapshot=> {
        snapshot.forEach((doc) => {
          if(doc!=null) {
            commit('addArtist', {id: doc.id, data: doc.data()})
          }
        })
      })
    }


#6
this.state.artists[payload.id] = payload.data

You are adding new state properties after initialization of the artists object. This can’t be detected by Vue.

See here for explanation and solution: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats


#7

@LinusBorg

Thank you!! I have solved with object.assign with the guide you have linked!! Thank you again!!!

this.state.artists = Object.assign({}, this.state.artists, {[payload.id]: payload.data})