Vue JS: vuex state not updating the component after change

Viewed 17931

I created an info-bar, an area I want to update with info from the component. I added it as a child of App.vue :

<template>
  <div id="app">
    <InfoBar />  // my info-bar
    <router-view/>
  </div>
</template>

To be able to update m<InfoBar /> from other components, I decided to try using Vuex and use mutations to change info:

Vuex Store:

   export const store = new Vuex.Store({
        state:{
            infoBarText: "Text from Vuex store" ,  // initial text for debugging         
        },
        mutations:{
            setInfoBarText(state,text){
                state.infoBarText = text;
            }
        }

infobar.vue

<template>
  <div>
    {{infoString}} // the result is always "Text from Vuex store"
  </div>
</template>

<script>
export default {
  name: "infoBar",
  data() {
    return {
      infoString: this.$store.state.infoBarText      
    }
  }

Now, I would like to update the text using the Vuex mutation from other component:

other.vue:

mounted() {
 this.$store.commit("setInfoBarText", "Text from Component");
}

I checked the state of infoBarText with Vue developer tools and it successfully changed to "Text from Component" but it's not changed the text in the component.

What I am doing wrong?

1 Answers

You should be using computed instead of data, because data itself is not reactive once it is assigned. This will fix your issue:

export default {
  name: "infoBar",
  computed: {
    infoString: function() {
      return this.$store.state.infoBarText;
    }
  }
}

Proof-of-concept:

const infobar = Vue.component('infobar', {
  template: '#infobar-template',
  computed: {
    infoString: function() {
      return store.state.infoBarText;
    }
  }
});

const store = new Vuex.Store({
  state: {
    infoBarText: "Text from Vuex store", // initial text for debugging         
  },
  mutations: {
    setInfoBarText(state, text) {
      state.infoBarText = text;
    }
  }
});

new Vue({
  el: '#app',
  methods: {
    updateText() {
   store.commit("setInfoBarText", "Text from Component");
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
<div id="app">
  <InfoBar></InfoBar>
  <button @click="updateText">Update text</button>
</div>

<script type="text/x-template" id="infobar-template">
  <div>
    {{infoString}}
  </div>
</script>

Related