John Freedom
John Freedom

Reputation: 481

Vuex nested objects

I am working on a app in vue right now that has an object with a few nested objects. Right now in my school object in the user object I can display the school object, but when I try to get the name attribute of the school object I get undefined for the name attribute when it has a value.

This is my state of the application:

{
 "user": {
  "user": {
   "name": "Test",
   "email": "[email protected]",
   "avatar": "http://www.gravatar.com/avatar/xxxx=300",
   "city": null,
   "state": null,
   "zip": null,
   "address": null,
   "lat": null,
   "long": null,
   "school": {
    "id": 1,
    "about": null,
    "header": null,
    "name": "Test",
    "user_id": 1,
    "created_at": "2018-06-06 19:48:16",
    "updated_at": "2018-06-06 19:48:16"
   },
   "following": [],
   "followers": [],
   "social_networks": [{
    "id": 4,
    "user_id": 1,
    "social_network_id": 1,
    "network_url": "test.com/k",
    "created_at": "2018-06-06 23:11:09",
    "updated_at": "2018-06-06 23:15:19"
   }, {
    "id": 5,
    "user_id": 1,
    "social_network_id": 2,
    "network_url": "test.com/k",
    "created_at": "2018-06-06 23:15:19",
    "updated_at": "2018-06-06 23:15:19"
   }, {
    "id": 6,
    "user_id": 1,
    "social_network_id": 5,
    "network_url": "test.com/k",
    "created_at": "2018-06-06 23:16:15",
    "updated_at": "2018-06-06 23:16:15"
   }]
  }
 },
 "socialNetowrks": {
  "available_networks": [{
   "id": 1,
   "network_name": "Facebook",
   "created_at": null,
   "updated_at": null
  }, {
   "id": 2,
   "network_name": "Instagram",
   "created_at": null,
   "updated_at": null
  }, {
   "id": 5,
   "network_name": "Twitter",
   "created_at": null,
   "updated_at": null
  }]
 }
}

Here are my getters

const getters = {
    name(state){
        return state.user.school.name
    }
};

const mutations = {
    FETCH_USER(state,user){
        state.user = user;
    }
};

const actions = {
    getUser: ({commit}) => {
        axios.get('/user').then(response => {
            commit('FETCH_USER', response.data);
        });

    }
}

When I just return the school object I get the object

{
 "id": 1,
 "about": null,
 "header": null,
 "name": "Test",
 "user_id": 1,
 "created_at": "2018-06-06 19:48:16",
 "updated_at": "2018-06-06 19:48:16"
}

But when I return state.user.school.name I get undefined. Does Vuex not work if you have nested objects?

Upvotes: 9

Views: 12098

Answers (3)

Romain
Romain

Reputation: 53

Seems like a Vue reactivity issue, as described in VueJS and Vuex documentations :

https://v2.vuejs.org/v2/guide/reactivity.html

https://vuex.vuejs.org/guide/mutations.html#mutations-follow-vue-s-reactivity-rules

Vue cannot detect property addition or deletion. You can either declare all your properties with empty values from the start, or use Vue.set(), or replace your state object with a fresh new one using Object.assign() or ES6 spread operator :

state.user = { ...user }

Upvotes: 4

ekqnp
ekqnp

Reputation: 394

I have exactly the same problem, indeed the console shows the object is populated, but accessing its child property returns undefined. My code has the same structure (fetching data with axios in an action, then commiting mutation). I have a simple getter:

getters: {
    users: state => state.users,
},

From a component, I perform:

console.log(this.$store.getters.users);
console.log(this.$store.getters.users.preprod);

and believe it or not, the output is:

> {…}
    __ob__: Object { value: {…}, dep: {…}, vmCount: 0 }
    preprod: Array(4) [ {…}, {…}, {…}, … ]
    <prototype>:  Object { … }
> undefined

The only clue I have for the moment is that these values are gotten from a script called cjs.js located at wbepack-internal:///./node_modules/cache-loader/dist/cjs.js. So may this be an issue with webpack caching?

Upvotes: 1

Sojourner
Sojourner

Reputation: 71

I ran in to this problem and resolved it by defining the nested object/property needed when declaring state, even if the value is empty or null to start.

So the minimum you would need to stop getting undefined for state.user.school.name would be.

const state = {
  user: {
    school: {
      name: ''
    }
  }
}

Obviously you will want to continue to expand that for other nested properties you need defined.

Upvotes: 7

Related Questions