Search code examples
javascriptvue.jsvuex

My Vue.js Vuex store has 2 actions that make GET requests. The second action requires the response from the first one in order to work. How to do it?


I have 2 actions that make GET requests and save the response in the Vuex store. The first action getVersion() gets the most recent version of the game and that version is required in order to make the second GET request. Right now I've hard coded the version in the second action, however, my goal is to concatenate it inside the URL.

Sadly I'm not sure how to access it from inside the function. Console.log(state.version) returns null for some reason even though it shouldn't be. I call these functions from inside App.vue like this:

mounted(){
    this.$store.dispatch('getVersion')
    this.$store.dispatch('getChampions')
}

Vuex store

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        version: null,
        champions: null
    },
    mutations: {
        version(state, data){
            state.version = data.version
        },
        champions(state, data){
            state.champions = data.champions
        }
    },
    actions: {
        getVersion({commit}){
            axios.get("http://ddragon.leagueoflegends.com/api/versions.json")
            .then((response) => {
                commit('version', {
                    version: response.data[0]
                })
            })
            .catch(function (error) {
                console.log(error);
            })
        },
        getChampions({commit, state}){
            axios.get("https://ddragon.leagueoflegends.com/cdn/9.24.1/data/en_US/champion.json")
            .then((response) => {
                commit('champions', {
                    champions: response.data.data
                })
            })
            .catch(function (error) {
                console.log(error);
            })
        }
    },
    getters: {
        version: (state) => {
            return state.version;
        },
        findChampion: (state) => (id) => {
            let championId = id.toString();
            let champion = Object.values(state.champions).find(value => value.key === championId);

            return champion
        }
    }
})

Solution

  • With this part:

    this.$store.dispatch('getVersion')
    this.$store.dispatch('getChampions')
    

    The second dispatch doesn't wait for the first one to finish. Meaning that it is firing before the first one has had a chance to finish getting the version.

    You need to create a promise that should resolve before the second dispatch is called.

    You could try doing it this way:

    async mounted(){
        await this.$store.dispatch('getVersion')
        await this.$store.dispatch('getChampions')
    }
    

    or if you don't want to use async/await

    this.$store.dispatch('getVersion').then(() => { 
        this.$store.dispatch('getChampions');
    });
    

    And in the action you should add return to the request (this is important):

    return axios.get(...