Search code examples
vue.jsvue-componentvuexvuex-modules

Iterating over a Vuex store object


I'm new to Vue.js and Vuex and trying out a sample app. This is the scenario-

I have a store module for notifications which stores the notifications in an object with a given name as its key.

{
  'message1': {
    type: 'info',
    message: 'This is an info message.',
    isShown: true,
  },
  'message2': {
    type: 'success',
    message: 'This is a success message.',
    isShown: true,
  },
  'message3': {
    type: 'error',
    message: 'This is an error message.',
    isShown: true,
  }
}

And this is my Vuex module that handles notification-

const state = {
  notifications: {},
};

const mutations = {
  setNotification(state, { message, type, name }) {
    state.notifications[name] = {
      message,
      type,
      isShown: true,
    }
  },
  removeNotification(state, name) {
    delete state.notifications[name];
  }
};

const actions = {
  async showNotification(context, options) {
    await context.commit('setNotification', options);
  },
  async removeNotification(context, name) {
    await context.commit('removeNotification', name);
  }
}

const getters = {
  isNotificationShown: (state, getters) => {
    return getters.getNotificationMessageList.length > 0;
  },
  getNotificationMessageList: state => {
    return state.notifications;
  },
}

export default {
  state,
  actions,
  mutations,
  getters,
}

And this is my component-

<template>
  <div v-if="isShown">
    <div v-for="(notice, name, index) in notificationMessageList" :key="name">
      {{ index }} - {{ notice.type }} - {{ notice.message}}
    </div>
  </div>
</template>

<script>
export default {
  computed: {
    isShown() {
      return this.$store.getters.isNotificationShown;
    },
    notificationMessageList() {
      return this.$store.getters.getNotificationMessageList; 
    },
  },
};
</script>

I checked with the Vue Development tool and found that the store does get updated and so does the component with the notification messages that I'm passing to the store. But the component is not being rendered. But if I use the same data by hardcoding it in the component, it works.

I'm not sure if this is the right way to connect the Vuex store to a component.


Solution

  • It's Vue reactivity problem. You need to update the reference to make Vue reactive. You can use JSON.parse(JSON.stringify()) or use ES6 syntax:

    const mutations = {
      setNotification(state, { message, type, name }) {
        state.notifications = {
          ...state.notifications,
          [name]: {
            message,
            type,
            isShown: true
          }
        }
      },
      removeNotification(state, name) {
        const newNotifications = {...state.notifications}
        delete newNotifications[name]
        state.notifications = newNotifications
      }
    };