Vue doesn't update view when array of objects get changed


#1

I think I have a problem with using Vuex and WebSockets. I have a list of appointments and when a user change the value it gets detected by an event listener. The function will send the data to my server, which notifies all the other active clients with the new data. In the end the data gets changed and I see the updated record also in the store (in state and as getter). It simply doesn’t update the view.

Vue doesn't update my getter

The strange thing is that the view gets updated correctly in the browser that updated the record. So the action and mutation functions are working. Vuex or Vue seems to have issue detecting a change in a watch function?

Does anyone know the solution to this problem?

Code (stripped) example:

// Agenda component (cleaned)
export default {
    name: 'Agenda',
    created() {
        this.$appointmentHub.$on('appointment-changed', this.onAppointmentChanged);
    },
    beforeDestroy() {
        this.$appointmentHub.$off('appointment-changed', this.onAnswerCountChanged);
    },
    methods: {
        onAppointmentChanged(appointment) {
            this.$store.commit('appointments/updateAppointment', appointment);
            // Tried with dispatch too
        },
    },
};

// Store (module/appointment)
export default {
    namespaced: true,
    state: {
        items: [],
        selectedDate: moment(),
    },
    getters: {
        appointmentsByDate(state) {
            return _.chain(state.items)
                .filter(/* some filtering */)
                .sortBy(['startDate', 'title'])
                .groupBy('groupBy')
                .value();
        },
    },
    mutations: {
        updateAppointment(state, appointment) {
            state.items = [
                ...state.items.filter(element => element.id !== appointment.id),
                appointment,
            ];
        },
    },
    actions: {
        updateAppointment({ commit, rootState }, { id, appointment }) {
            return fetch(`${rootState.$appUrl}/appointment/${id}`, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(appointment),
            })
                .then(() => {
                    commit('updateAppointment', appointment);
                    return appointment;
                });
        },
    },
};

// Component that has the uses the getter
export default {
    name: 'AppointmentList',
    computed: {
        appointments_() {
            return this.$store.getters['appointments/appointmentsByDate'];
        },
    },
};

#2

I don’t see the problem right away. Can you try if you run into the same issue if you reference the store directly instead of using a getter? So do:

export default {
  computed: {
    appointments_() {
      return this.$store.state.appointments.items;
    },
  },
};

#3

Thank you for your answer! I have tried that but sadly does not work. The strange thing is that it does update correctly, but the event that gets triggered (websockets) does not update the view. I do have another issue with my update process. I will post that question later in the forum, maybe it is linked to this issue. Anyways I have tried changing all the mutations with Vue.set, but sadly does not work as well.

Update: I have posted my other question, maybe they are the same issue: Getter in Vuex doesn't update Vue components but the data is available)


#4

Perhaps you can try this. I’m not sure if it works, but it’s worth a try:

export default {
  mutations: {
    updateAppointment(state, appointment) {
      state.items = state.items.map((item) => {
        if(item.id === appointment.id) {
          return appointment;
        }

        return item;
      });
    }
  }
};

#5

Sadly it didn’t work, but thank you so much for helping out! :slight_smile: