Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue JS: vuex state not updating the component after change [duplicate]

Tags:

vue.js

vuejs2

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?

like image 644
Eyal Avatar asked Jan 14 '19 20:01

Eyal


People also ask

How do I update my Vuex state?

Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state changes. You cannot directly mutate the store's state. The only way to change a store's state is by explicitly committing mutations.

Does Vuex state persist on refresh?

To persist Vuex state on page refresh, we can use the vuex-persistedstate package. import { Store } from "vuex"; import createPersistedState from "vuex-persistedstate"; import * as Cookies from "js-cookie"; const store = new Store({ // ...

How do I Rerender components in Vue?

Key-changing to force a component refresh We add a key attribute to our component, and then change that key whenever we need the component to be re-rendered. Every time that forceRerender is called, the value of componentKey will change.

Are Vuex mutations synchronous?

In Vuex, mutations are synchronous transactions: store. commit('increment') // any state change that the "increment" mutation may cause // should be done at this moment.


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>
like image 153
Terry Avatar answered Sep 28 '22 05:09

Terry