Home » vue » How to wait for action to complete before accessing the Vue Store state?

How to wait for action to complete before accessing the Vue Store state?

Posted by: admin November 26, 2021 Leave a comment

Questions:

I have Vuejs/Nuxtjs application within which I need to access a Vuex store state after it has been modified by Vuex action. Currently when I try to run the action and assignment then I get the old state and not the one which was updated after action.

How to make the code wait for action completion then run the next statement? Following is the code I have currently:
Vuejs Component:

<template>
  <div>
    <input v-model="formData.value" type="text">
    <button @click="performAction">
      Click Me
    </button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      formData: {
        value: '',
        returnValue: ''
      }
    }
  },
  methods: {
    performAction () {
      // Set the value within the Vuex Store
      this.$store.commit('modules/DataStore/populateData', this.formData.value)

      // Perform the Action
      this.$store.dispatch('modules/DataStore/getData').then(() => {
        console.log("AFTER COMPLETE ACTION")
      })

      // Assign the update value to the variable
      this.formData.returnValue = this.$store.state.modules.DataStore.data
    }
  }
}
</script>

<style>
</style>

Vuex Store:

export const state = () => ({
  data:''
})

export const mutations = {
  populateData (state, data) {
    state.data = data
  }
}

export const actions = {
    getData ({ commit, state, dispatch }) {
        const headers = { 'Content-Type': 'application/json' }
        this.$axios
            .post('/getUrlData', state.data, { headers })
            .then((response) => {
                console.log("WITHIN RESPONSE")
                commit('populateData',response.data)
            })
            .catch((error) => {
                commit('populateData', 'Unable to obtain data, Error : ' + error)
            })
    }
}

Following are the thing I tried and nothing is working at the moment:

  1. I tried the .then() function.
  2. I tried Async and await but both are not working

Any suggestions will be really appreciated. Thanks in advance.

Answers:

You need to return your promise in your if you want to chain it in the calling method. eg:

getData ({ commit, state, dispatch }) {
    const headers = { 'Content-Type': 'application/json' }
    return this.$axios  // now this promise will be returned and you can chain your methods together
        .post('/getUrlData', state.data, { headers })
        .then((response) => {
            console.log("WITHIN RESPONSE")
            commit('populateData',response.data);
            return response.data; //this will allow you do send the data through to the next Then() call if you want to
        })
        .catch((error) => {
            commit('populateData', 'Unable to obtain data, Error : ' + error)
        })
}

This situation is a lot easier to manage with async-await IMO. It becomes:

export const actions = {
    async getData ({ commit, state, dispatch }) {
        const headers = { 'Content-Type': 'application/json' }
        const response = await this.$axios.post('/getUrlData', state.data, { headers });
        console.log("WITHIN RESPONSE")
        commit('populateData',response.data);

     }
}

and

methods: {
async performAction () {
    // Set the value within the Vuex Store
    this.$store.commit('modules/DataStore/populateData', this.formData.value)

     // Perform the Action
     await this.$store.dispatch('modules/DataStore/getData');
     console.log("AFTER COMPLETE ACTION");

    // Assign the update value to the variable
    this.formData.returnValue = this.$store.state.modules.DataStore.data
   }
}

###

You can create getter in vuex :

export const getters = {
  getData: (state) => state.data,
};
export const actions = {
  async setData ({ commit }, data) {
    const headers = { 'Content-Type': 'application/json' }
    await this.$axios
      .post('/getUrlData', data, { headers })
      .then((response) => {
        console.log("WITHIN RESPONSE")
        commit('populateData',response.data)
      })
      .catch((error) => {
        commit('populateData', 'Unable to obtain data, Error : ' + error)
      })
  }
}

then in component you can map getters and actions, and call them :

import { mapGetters, mapActions } from 'vuex'

computed: {
...mapGetters(['getData']),
},
methods: {
  ...mapActions(['performAction']),
 
  async performAction() {
    await this.setData(this.formData.value)
    this.formData.returnValue = this.getData
  }
}