aidonsnous
aidonsnous

Reputation: 1503

Vuex getters are returning null with asynchronous actions

My store has the following code :

export default {
state:{

},
actions : {
loadData ({commit}){
    const response = await axios.request({url:'http://mydata.com/data',method:'get'});
    commit('setData', response.data);
    console.log("Value set", response.data);
}
},
mutations: {
    setData(state,data){
        state.names = data.names;
        state.values = data.values;

    }
},
getters: {
    getNames() {
    return state.names() ; 
    },
    getValues() {
        return state.values();
    }
}
}

In my parent component I have :

 <template>
        <div>
            <child-element :values="getValues"></child-element>
        </div>
    </template>
    <script>
    import {mapGetters,mapActions}
    export default {
        computed: {
            ...mapGetters(['getValues'])
        },
        created(){
            loadData();
console.log(getValues);
        }
    }
    </script>

My child component :

<template>
    <div>
        <h1> {{ values["ma"] }}
    </div>
</template>

<script>
    export default {
        props:{
            values
        }
        mounted(){
            console.log(this.values);
        }
    }
</script>

The problem is that the this.values in child component is always displaying undefined and the message value set from the actions is being logged after the message of child component; the getValues is undefined in parent and values prop is undefined in child componenent

From my expectation it should not be undefined thinking the mount event of parent will come after create and since create is where the data used in getter are being set the values by the time the child is being mounted should be set.

What am I missing to have my data fetched and used properly ?

Upvotes: 1

Views: 3989

Answers (2)

Anatoly
Anatoly

Reputation: 22758

  1. You need to declare names and values in the state:
state:{
  names: null, // or [] if you wish to always have an array 
  values: null // or [] if you wish to always have an array  
},
  1. Correct your getters like this:
getters: {
    getNames: state => state.names,
    getValues: state => state.values
}
  1. You need to add await keyword while calling loadData in a component (and add async to a method as well).

Upvotes: 1

Ohgodwhy
Ohgodwhy

Reputation: 50767

You're never awaiting on your asynchronous action to fire from Vuex:

created(){
  loadData();
  console.log(getValues);
}

Should become:

async created() {
    await this.loadData()
    console.log(getValues)
}

Your action should return a promise upon completion as well:

actions : {
  async loadData ({commit}){
    const response = await axios.request({url:'http://mydata.com/data',method:'get'});
    commit('setData', response.data);
    console.log("Value set", response.data);

    return Promise.resolve()

  }
}

Upvotes: 5

Related Questions