Skip to main content
  1. Posts/

How do you maintain multiple loading states in Vuex?

·602 words·3 mins
Joe Erickson
Author
Joe Erickson
Senior software developer specializing in web development, AI, and helping others learn to code.
Table of Contents

One of the best ways to improve the user experience in a dynamic application is by setting up loading icons for data coming into your Vuex store. But if you’ve ever tried to set this up on a page with a lot of components that are loading different dynamic data. How do you show the user that data is being loaded when that data might be coming from different, parallel API calls?

Your first attempt might be to have a loading value in your Vuex store that you set to true when you are loading in data and false once the data is loaded. But that quickly becomes not good enough once you are loading in multiple calls.

And there are a number of other schemes that just don’t cut it either. Things like incrementing a loading count or checking to see if data is filled in or not–which I do talk about in How to show a loading icon before data is loaded in Vue and Vuex but is only reliable in simple data loads. All of these have edge cases that pop up and ruin things at some point.

Using a status map
#

A better way to handle this is to use a status map within Vuex (assuming Vuex is where you are making the API calls, as described in How to query your API using Vuex in your Vue application).

A status map is an object in your Vuex store that you use to keep metadata information about the data that you’ve loaded, the state of it, and any other information that you want to keep track of for it. By having a single source for this information, you’ll have a one stop location for all of your components to get updates on the current status of the data they care about. I’m going to show this with a loading status for the data, and an error status.

You can set this up in your Vuex state with:

state: {
  posts: [],
  users: [],
  status: {
      users: {
          loading: false,
          error: false
      },
      posts: {
          loading: false,
          error: false
      }
  }
},

You can then set statuses in a mutation, just like we would any dynamically loaded data. Here’s what that would look like for the users state:

mutations: {
  SAVE_USERS(state, users) {
    state.users = users;
  },
  SAVE_LOADING(state, dataName, status) {
    // create a property in status
    state.status[dataName].loading = status;
  },
  SAVE_ERROR(state, dataName, status) {
    // create a property in status
    state.status[dataName].error = status;
  }
},

actions: {
  loadUsers({commit}) {
    commit('SAVE_STATUS', 'users', true);
    Vue.axios.get('users').then(result => {
      commit('SAVE_USERS', result.data);
      commit('SAVE_STATUS', 'users', false);
    }).catch(error => {
      commit('SAVE_ERROR', 'users', true);
      commit('SAVE_STATUS', 'users', false);
      throw new Error(`API ${error}`);
    });
  }
}

With these statuses set, we can now use them in our component. If we have a component that uses users and posts, for example, we could add this if to the loader:

<div v-if="$store.state.status.users.loading || $store.state.status.posts.loading">
  <img src="./../assets/loading icon.png">
</div>
<table class="users" v-else>
  <!-- data display once the data is loaded -->
</table>

The above will only show the table once the users and posts loading statuses are both false. And you can set up the same sort of logic for showing an error status as well.

This way of handling statuses are something I found by looking at how Vue Apollo handles loading state and realized that the same thing could be used for Vuex as well. It makes is super easy for a component to watch for the data that it cares about only.

Try this out and see if it doesn’t make handling loading states a lot easier.

Related

How to Load Vue Components on Non-SPA Sites

·970 words·5 mins
There are times when you want to use Vue components, but the application you’re working on is still in the age of jQuery. Is there a way to start using Vue without switching everything to Vue and making a single page application? Can we get all of that beautiful, juicy component action without breaking everything else that’s currently on the site? Also, can we add Vue components without having to rewrite the entire website to use Vue?