[Vuejs]-Vuex state in Vue.js computed returning before initialised

1👍

Seeing your problem, you can setup a watcher on a Vuex store getter and perform your task once you get a value.

Define getter as

getters: {
    getBoardData: state => state.boardColumnData
}

and map your getter and create a watcher as

computed: {
    ...mapGetters(['getBoardData'])
},
watch: {
    getBoardData: {
        immediate: true,
        handler(to, from) {
            if(to) {
                //handle your changes
                this.populate()
            }
        }
    }
}

If you had the action dispatched in the same component, as actions are asynchronous, you could have chained a callback and called populate() on completion.

0👍

You seem to be forgetting to actually dispatch the action to get the data. Try this in your created hook:

created() {
  this.$store.dispatch('Dashboard', 'getAllBoardPostData');
  this.populate();
}

EDIT:

Dispatching the action in another component is okay. In that case, the created hook might be too early in the lifecycle to wait for the data being fetched (since this component doesn’t know about the one doing the dispatch), and it only runs once. You could add a watcher to wait for the computed property to change and trigger a side-effect (the populate method).

watch: { 
  boardColumns() { 
    this.populate() 
  } 
}

Or, if the data is essential to render the component, you could consider using the data to determine a v-if in the parent component as @Estus Flask suggested. Depending on how your component is structured in terms of reuse and tight coupling to the store, you could even pass it down as props at that point.

// Parent component.vue

<template>
  <Doughnut 
    v-if="boardColumns && boardColumns.length"
    :boardColumns="boardColumns"
  />
</template>

<script>
import Doughnut from './Doughnut.vue'

export default {
  components: {
    Doughnut,
  },
  computed: {
    boardColumns() {
      return this.$store.state.Dashboard.boardColumns
    }
  }
}
</script>

// Doughnut.vue

<template>
  <div>
    {{ boardColumns }}
  </div>
</template>

<script>
  export default {
    name: "Doughnut",
    props: {
      boardColumns: {
        type: Object,
        required: true,
      }
    },
    created() {
      this.populate();
    },
    methods: {
      populate() {
        console.log(this.boardColumns) 
      }
    }
};
</script>

0👍

This is a normal behaviour the component will render before the Vuex store. When the computed section will check there won’t be data initialised in the store.

This could happen when you’re using XHR request to get the store data.

The solution is to use v-if condition where the computed property is using. In your case you can check

v-if = "boardColumns.length>0"
👤Rijosh

Leave a comment