Search code examples
vue.jsvuexflux

Vuex issue transforming data into observer


I am using Vuex to manage the state of my application. When I am dispatching an action that calls some data from a server API, and if then this action commits a mutation, somehow my data gets transformed to observer objects instead of the actual data. Is this an expected behaviour or a bug within vuex?

Action:

async getDataFromApi(context, payload) {
try {
    let data = callApi(foo);
    context.commit("SET_REPORTING_DATA", { data, id: payload })
    return data;
} catch (e) {
  console.log(e.code);
  console.log(e.message);
  return false;
}}

Mutation

SET_STATE(state, data) {
state.list = { ...state.list, [data.id]: data.data }
}

The weird part about this is that when I log the data that I get from the API, I get an observer object although I am returning the original data from the api.


Solution

  • That's not an issue but instead a caveat between the browser and Vue's reactivity system. To learn more about Vue's reactivity check their docs on Reactivity in Depth, there they explain how it works and even mention this caveat:

    One caveat is that browser consoles format getter/setters differently when converted data objects are logged...

    And they recommend to use vue-devtools for a friendlier introspection interface.

    However there is a way to see logged variables with their data without having to use vue-devtools, the way is to log them using console.log(JSON.parse(JSON.stringify(data))), as shown below, to verify it correctly use the browser console, as StackOverflow's console already shows without the observer.

    var app = new Vue({
      el: '#app',
      data: () => ({
        obj: {
          a: 123
        }
      }),
      created() {
        console.log('Observer');
        console.log(this.obj);
        console.log('Data');
        console.log(JSON.parse(JSON.stringify(this.obj)));
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app"></div>