Vuex in Nuxt: Breaking down the Store into Modules

Let me show you how to move everything out of an overcrowded root store file into separate easier to maintain module files.

Using a store to manage the state is important for every big application. That’s why Nuxt.js implements Vuex in its core. In this article, I’m assuming you have a single store/index.js handling all of your state. This is the Classic mode. When starting out and learning, it can be easier to choose this.

However, when the project starts becoming bigger this single file will inevitably start getting long, crowded, and hard to maintain. To avoid all this drama, simply use the Modules mode right from the start. Assuming that you didn’t, in this article, I will show you how to easily convert your single store/index.js file into easier to maintain modules.

When working with the Vuex Store in Nuxt, there are 2 store modes that can be chosen:

  • Classic (deprecated): store/index.js returns a store instance.
  • Modules: every .js file inside the store directory is transformed as a namespaced module (index being the root module).

Assuming I have a single store/index.js file that I would like to break down into 3 modules.

  1. user.js
  2. loading.js
  3. services.js

The first step to Modules transcendence is to create 3 files: store/user.js, store/loading.js, store/services.js, and then move all the code from inside store/index.js to their relevant destinations. The store/index.js can be deleted if there’s nothing left in there.

Updating Vuex Store Methods

Now that the code is in Modules, all methods that may have been used in components to interact with mutations, actions, getters, and state in the old store/index.js will have to be updated. For example, the getServices action could be dispatched in Classic mode by using:

dispatch("getServices")

When moving an action into its own separate module file, leaving dispatch methods untouched will inevitably cause errors such as this:

Since getServices is not in store/index.js anymore, the dispatch method will need to be updated to its new modular location:

dispatch("services/getServices")

The services/ portion refers to the store/services.js file. The getServices portion refers to the name of the action in that file.

Vuex Map Helpers

When a component needs to make use of multiple store state properties or getters, declaring all these computed properties can get repetitive and verbose. To deal with this we can make use of the mapState helper which generates computed getter functions for us, saving us some keystrokes: For example, instead of using:

this.$store.dispatch("deleteService", payload)

in a component’s method, use mapActions by doing the following:

  1. Import the helper(s) needed from Vuex in your component:
    import { mapActions } from “vuex”
  2. Inside of the methods object of your component, add the mapper:
    …mapActions({ removeService: "service/deleteService" }),
  3. Then, the new dispatch action can be rewritten as: this.deleteService(payload)

Dispatching Modular Actions within Actions

In store/services.js, I’m using dispatch methods to trigger the actions startLoading and stopLoading to start and stop a loader. Since these 2 actions are now modularized in store/loading.js, the old way of dispatching them such as dispatch("startLoader") will no longer work. Dispatching actions inside of other actions needs to be done like this:

dispatch("loading/startLoading", null, { root: true })

The 2nd argument (in this case, null) needs to be there and the { root: true } object will instruct Vuex to look for startLoading, starting from the root store instead of starting from its current location of invocation store/services.js.

PS.

The nuxtServerInit action only works in the root module. In that case, you’d need to keep the store/index.js root module. Only the primary module (in store/index.js) will receive this action. You'll need to chain your module actions from there.

I hope you found this useful, let me know your thoughts in the comment section.

Hi, my name is Alex. I’m a front-end engineer, passionate for the web, responsive design, & typography.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store