Vue.js reactivity of complex objects in a store

Viewed 382

My Problem

I am trying to store a list of complex items in a store and access these items from a component. I have a mqtt interface which receives data for these items and updates their values in the store. However, the ui does not react to updating the properties of these items.

Structure

In my store, i have two mutations:

state: {
  itemList:{}
},
mutations: {
  /// adds a new item to itemList
  [ADD_ITEM](state, item) {
    if (item&& !state.itemList[item.itemId])
    {
      Vue.set(state.itemList, item.itemId, item);
    }
  },
  /// updates an existing item with data from payload
  [SET_ITEM_STAT](state, { itemId, payload }) {
    var item= state.itemList[itemId];
    if (item) {
      item.prop1 = payload.prop1;
      item.prop2 = payload.prop2;
    } 
  }
},
actions: {
  /// is called from outside once when connection to mqtt (re-)established
  initializeMqttSubscriptions({ commit, dispatch }, mqtt){
    mqtt.subscribeItem("items/stat", async function(itemId, topic, payload) {
      commit(SET_ITEM_STAT, { itemId, payload });
    });
  },
  ...
}

I also tried:

  • setting the item properties using Vue.set(state.itemList, itemId, item);
  • setting the item properties using Vue.set(state.itemList[itemId], 'prop1', payload.prop1);

I also want to show how i built the Component which accesses and displays these items (Item.vue). It is one component, that gets passed the itemId to show via the route params. I've got the following computed properties:

<template>
<div class="grid-page">
    <h1 class="page-title">Item- <span class="fw-semi-bold">{{ id }}</span></h1>
    <div>
        <Widget v-if="item">
            {{ item.prop1 }}
...
...
computed: {
  id(){
    return this.$route.params.itemId;
  },
  item(){
    return this.$store.state.items.itemList[this.id];
  }
}

So when the route parameter itemIdchanges, i successfully can see the item data, everything is fine. But if i update the properties of an item with the mutation shown above, no update in view is triggered.

I would be very happy if someone could give me a hint what i am doing wrong here. Thanks in advance!

1 Answers

Since i can't comment to ask for some clarifications,

If you're itemlist is an nested object, try out with Object.assign


[SET_ITEM_STAT](state, { itemId, payload }) {
    var item= state.itemList[itemId];
    if (item) {
this.state.itemList[itemId] = Object.assign({}, this.state.itemList[itemId].prop1, {payload.prop1})
this.state.itemList[itemId] = Object.assign({}, this.state.itemList[itemId].prop2, {payload.prop2})

// or
this.state.itemList[itemId] = Object.assign({}, this.state.itemList[itemId], {prop1: payload.prop1, prop2: payload.prop2})
    } 
  }

Let me know how it goes

https://v2.vuejs.org/v2/guide/reactivity.html#For-Objects

Related