Search code examples
javascriptvue.jsvuejs2vue-componentvuex

Displaying VueJS getter data in template / async


In a VueJS component named GlobeInformation.vue, I would like to call a getter "mapData" which I expect to return a manipulated version of my state's data, however when I display it in my template it shows up as an empty array. I've posted a stripped down relevant version of my code below. Thanks in advance.

PS : I suppose this happens due to the async API call, hence I tried using v-if conditions to check if the data has been received only then render it on the template.

GlobeInformation.vue

<template>
<div class="information">
    <div v-if="mapDataLoaded">
        {{ mapInformation }}
    </div>
</div>
</template>
<script>
export default {
    data: function() { 
        return { 
            mapDataLoaded: false,
            mapInformation: []    
        }
    },
    computed: {
        ...mapGetters(['mapData'])
    },
    methods: {
        ...mapActions(['fetchCondensedDetails'])
    },
    async mounted() {
        await this.fetchCondensedDetails('/')
        this.mapInformation = await this.mapData
        this.mapDataLoaded = true
    }
}
</script>

getters.js

export default {
    mapData: state => {
        let mapData = []
        state.condensed.forEach(country => {
            mapData[country.alpha_2] = country.confirmed
        })
        return mapData
    }
}

actions.js

export default {
    async fetchCondensedDetails({ commit }, path) {
        try {
            if (path === '/') {
                const res = await fetch('https://covidapi.info/api/v1/global/latest')
                commit('SET_CONDENSED_DETAILS', await res.json())
            }
        } catch (err) {
            console.log(err)
        }
    }

}

mutations.js

export default {
    SET_CONDENSED_DETAILS: (state, data) => {
        data.result.forEach((element, index) => {
            const key = Object.keys(element)[0]

            let details = countries.find(country => {
                if (country.alpha_3 === key) return country
            })

            if (details) {
                state.condensed.push({
                    ...data.result[index][key],
                    alpha_3: key,
                    alpha_2: details.alpha_2,
                    name: details.name
                })
            }
        })
    }
}

Solution

  • We can't see the data structure of countries, so this is a bit of a guess, but should work as long as your data is properly unique. You can remove mapInformation and use the getter directly in the template:

    <div v-if="mapDataLoaded">
      {{ mapData }}
    </div>
    

    Change the getter's mapData to an object:

    mapData: state => {
      let mapData = {}; // <-- object instead of array
      ...
    }