DEV Community

loading...
Cover image for How to Greatly Simplify Your Vuex Store

How to Greatly Simplify Your Vuex Store

ratracegrad profile image Jennifer Bland Originally published at jenniferbland.com ・3 min read

As the size of your Vue application grows, the number of actions and mutations in your Vuex store grows too. Let me show you how to reduce this to something more manageable.

What is Vuex

Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.

How we are using Vuex

We are using Vuex to share state between all the applications in our Factory Core Framework application. Since the framework is a bundle of applications, we currently have nine Vuex stores. Each store has its own state, actions, and mutations. We are using actions in the store to do API calls to the backend. Once the data is returned we use mutations to store it in state. This allows any component to access that data. As you can imagine, our stores can have a very large number of actions to handle these API calls. Here is an example of all the actions in one of our Vuex stores.

This store has 16 actions. Now imagine how many actions our Factory Core Framework has in total if we have 9 stores!

Simplifying our Actions

All our actions basically perform the same functionality. Every action does the following:

  • fetch data from API (include payload if necessary)
  • (optionally) store data in state
  • return response to the component that called the action

To refactor these into a single action, we needed to know if the action needed to know:

  • an endpoint to hit
  • to send payload in the API call or not
  • to commit data to state or not, and if so, to which state variable

Our current action

Here is an example of one of our actions.

async getLineWorkOrders({ rootState, commit }, payload) {
    try {
        let response = await axios.post(
           'api.factory.com/getLineWorkOrders',
           Object.assign({}, payload.body, { language: rootState.authStore.currentLocale.locale }),
           rootState.config.serviceHeaders
        );
       commit( 'setCurrentWorkOrderNumber', response.data.currentWorkOrderNumber );

       return response.data;
    } catch (error) {
       throw error;
    }
},

In this action, we fetch data from our backend API by hitting the endpoint ‘api.factory.com/geteLineWorkOrders’. After the data is retrieved, the state variable currentWorkOrder is updated. Finally, the data is returned to the component that made the call. All our actions have this format. To refactor it into a single action we need to have the endpoint, whether or not to send payload and whether or not to commit data. Here is our refactored single action:

async fetchData({ rootState, commit }, payload) {
   try {
       let body = { language: rootState.authStore.currentLocale.locale };
       if (payload) {
           body = Object.assign({}, payload.body, body);
       }
      let response = await axios.post(\`api.factory.com/${payload.url}\`, body, rootState.config.serviceHeaders );
      if (payload.commit) {
          commit('mutate', {
              property: payload.stateProperty,
              with: response.data\[payload.stateProperty\]
           });
      }
      return response.data;
   } catch (error) {
      throw error;
   }
}

This single action will handle every possible call. If we need to send data with the API call it does. If we need to commit data it does. If it does not need to commit data, it does not. It always returns data to the component.

Using one mutation

Previously for every action that needed to mutate state, we created a new mutation to handle this. We replaced them all with a single mutation. Here is our single mutation:

const mutations = {
    mutate(state, payload) {
       state\[payload.property\] = payload.with;
    }
};

If an action needs to store data in state, we call this mutation like this:

commit('mutate', {
    property: <propertyNameHere>,
    with: <valueGoesHere>
});

Conclusion

We have greatly simplified our actions and mutations in our stores by having just one action and one mutation.

Training Courses

I create training courses on my website CodePrep. I have training courses on Vue, Webpack, Flexbox, functional programming and more. Check it out here.

Discussion (3)

pic
Editor guide
Collapse
ssimontis profile image
Scott Simontis

Thank you for writing this! This article is a great demonstration of removing boilerplate code. Most of your code segments are not highlighting syntax properly, you may want to investigate that.

I just moved back to Atlanta a few months ago and I was shocked by how unpopular Vue is around here. Most companies I have applied to use Angular, which was unheard of when I lived in DC. I find it fascinating how tooling preferences can change so much with geography.

Collapse
ratracegrad profile image
Jennifer Bland Author

Scott,

Welcome back to Atlanta. Glad you enjoyed the article. The use of technologies generally follow a ripple in the ocean pattern. If you drop a rock in ocean that is Silicon Valley then everybody wants to jump on the new technology and use it. I call it resume driven development or RDD. It takes time for that ripple to reach the east coast where technology choices are driven by best use of technology instead of wanting to jump on the latest bandwagon. For that reason most east coast companies pick a technology and stay with it for years.

Collapse
spacenomad profile image