1

In main.js of my app I dispatch an action that gets companies from my API and selects the first. This action dispatches every time, doesn't seem to fail here.

new Vue({
  el: '#app',
  store,
  router,
  render: h => h(App),
  created: function () {
    this.$store.dispatch('getCompaniesAndSelectFirst');
  }
})

In another view I need to retrieve campaigns that belong to the selected company, so I do this on mount with vue-resource.

mounted: function () {
  if (this.selectedCompanyId) {
    this.$http.get('Campaigns', {params: {companyId: this.selectedCompanyId}}).then(response => {
      // success callback
      this.numbersTableData = response.body;
    }, response => {
      // error callback
    });
  }
}

selectedCompanyId is my computed property that returns the id of the selected company in Vuex.

selectedCompanyId: function () {
  return this.$store.getters.selectedCompanyId;
}

The issue is selectedCompanyId is undefined at this point if this is the first view that's loaded.

If I refresh the page selectedCompanyId is still undefined and my get request fails.

If I open the application on this view, the selectedCompanyId is undefined and the get request fails, but if I route to another view and then route back selectedCompanyId has loaded and the request is successful.

If I open the application on another view, and then route to the view selectedCompanyId is defined and the get request is successful.

As I understand it this is because my get request that gets companies and selects the first one needs time to complete.

How can I solve this? Is there a better way to do what I'm trying to do?

Suren
  • 71
  • 1
  • 7
  • You need to guard the route based on the loaded state of the data. See https://router.vuejs.org/en/advanced/data-fetching.html – Phil Dec 27 '17 at 01:33
  • @Phil How would I go about doing that? Only thing I see I can do is not route if the state isn't loaded, how do I keep checking until it loads? – Suren Dec 27 '17 at 03:53
  • Did you read the document I linked? There's a section titled _"Fetching before navigation"_ – Phil Dec 27 '17 at 03:54

1 Answers1

1

I stopped dispatching the getCompaniesAndSelectFirst action in the created function of the Vue instance.

I modified the getCompaniesAndSelectFirst action to return a promise:

export const getCompaniesAndSelectFirst = ({ commit, state }) => {
  return Vue.http.get('Companies').then(response => {
    // get body data
    var companies = response.body;

    commit('getCompanies', companies);
    commit('selectCompany', companies[0].Id);
  }, response => {
    // error callback
  });
}

I created a navigation guard that dispatches the action if state does not contain a truthy value for selectedCompanyId, and only continues to the route once the promise returned from the action is resolved.

Suren
  • 71
  • 1
  • 7
  • 1
    This is excellent but you have implemented the [explicit promise construction antipattern](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it). There's no need to wrap `Vue.http.get()` in another promise. – Phil Dec 27 '17 at 05:33
  • @Phil Thanks for the heads up, fixed it (: – Suren Dec 27 '17 at 06:55