LundinCast
LundinCast

Reputation: 9810

How to wait on Vuex state initialization from a view component?

I'm building a Movie website to practice on VueJS. During app initialization, I get a list of movie genres from 3rd-party API. Since this list is needed in several components of the app, I manage and store it via Vuex, like so:

main.js:

new Vue({
  router,
  store,
  vuetify,
  render: h => h(App),
  created () {
    this.$store.dispatch('getGenreList')
  }
}).$mount('#app')

Vuex's index.js:

export default new Vuex.Store({
  state: {
    genres: []
  },
  mutations: {
    setGenreList (state, payload) {
      state.genres = payload
    }
  },
  actions: {
    async getGenreList ({ commit }) {
      try {
        const response = await api.getGenreList() // axios call defined in api.js
        commit('setGenreList', response)
      } catch (error) {
        console.log(error)
      }
    }
  }
})

Now, in my Home view, I want to retrieve a list of movies for each genres, something like this:

Home.vue:

<script>
import { mapState } from 'vuex'
import api from '../api/api'

export default {
  name: 'home',
  data () {
    return {
      movies: null
    }
  },
  computed: {
    ...mapState({
      sections: state => state.genres
    })
  },
  async mounted () {
    const moviesArray = await Promise.all(
      this.sections.map(section => {
        return api.getMoviesByGenre(section.id)
      })
    )
    this.movies = moviesArray
  }

}
</script>

The issue here is that, on initial load, sections===[] since genres list hasn't been loaded yet. If I navigate to another view and come back, sections holds an array of genres objects as expected.

Question: How can I properly wait on sections to be loaded with genres? (since the getGenreList action isn't called from that component, I can't use this method)

I was thinking in implementing the movie list retrieval in a Watcher on sections instead of in mounted() but not sure if it's the right approach.

Upvotes: 2

Views: 1678

Answers (1)

BigKamil5
BigKamil5

Reputation: 305

Yep, it is right approach, that's what watchers are for.

But if you only can... try to do actions like this one inside one component family. (parent passing props to children, controlling it);

You can read this article, about vuex - https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/. It will maybe clarify this idea. Just simply don't store in vuex everything, cause sometimes it' does not make sense

https://v2.vuejs.org/v2/api/#watch - for this one preferably you should use immedaite flag on watcher and delete mounted. Watcher with immedaite flag is kinda, watcher + created at once

Upvotes: 2

Related Questions