DEV Community

Jeremy Wynn
Jeremy Wynn

Posted on • Originally published at jeremywynn.com on

Vuex in Nuxt: Going from Classic store mode to Modules

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

  • Classic (deprecated): The presence of one single file `store/index.js` causes Nuxt to import Vuex and create store.
  • Modules: Every single `.js` inside the `store` directory becomes a namespaced module where each can have its own state, mutations, actions, getters, etc.

When starting out and learning, it can be easier to choose the Classic route and start off with a single store/index.js file. One such file that I've been working on in a project can be seen here as a Github gist.

Not only is this file becoming quite long, there are 3 different categories of state that I am using: Items, Loading, and User. I've grouped the relevant code under each to better illustrate. For example, all functions that involve mutations of Items are grouped under the // Items comment within mutations.

The first step to Modules nirvana is to create 3 files: store/items.js (gist), store/loading.js (gist), store/user.js (gist), and then move all the code from inside store/index.js to their relevant destinations. In my case, the store/index.js can be deleted.

Updating Vuex Store Methods

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

dispatch("getItems")

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

Vuex error - unknown action type: GET\_ITEMS

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

dispatch("items/getItems")

The items/ portion refers to the store/items.js file. The getItems portion refers to the name of the action in that file.

Vuex Map Helpers

Vuex offers map helpers such as mapState, mapGetters, mapActions, and mapMutations. Utilize these to make the code less verbose which is helpful when using store methods multiple times in a component. For example, instead of using:

this.$store.dispatch("deleteItem", 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({ removeItem: "items/deleteItem" }),
  3. Then, the new dispatch action can be rewritten as: this.removeItem(payload)

Dispatching Modular Actions within Actions

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

dispatch("loading/triggerBusyState", 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 triggerBusyState starting from the root store instead of from its current location of invocation store/items.

Some Notes

Having just store/index.js is actually Modules store mode where this file represents the root module. This article could be better described on how to move everything out of an overcrowded root module file into separate and more tidy module files.

It is still ok to have a root module store/index.js if needed. For example, the nuxtServerInit action only works in the root module.

My final working module mode store files (gists): items.js, loading.js, and user.js.

Oldest comments (2)

Collapse
 
simplenotezy profile image
Mattias Fjellvang

Thanks for the article. I'm just missing some information on how you use getters, you don't mention this at all.

Collapse
 
iansamz profile image
Ian Sam Mungai • Edited

Thanks alot. The store/index.js helped me out. But i got a weird way to get things to work. You can checkout this link to get more help nuxtjs.org/examples/vuex-store/