Vuex next steps: Namespaces and dynamic modules

The need to use some sort of state management system arises fairly early on in a VueJS project.

At the beginning we usually follow the basic tutorials suggesting to create a /store directory with all our store modules and register them in a store.js file. Something along these lines:

A simple store.js file

However not long before you realise that you have no way to differentiate actions and getters from different modules other than giving them long and over-descriptive names. For example, you can’t name an action getInfo in user module as any other module might have that action name too. You can either name it getUserInfo which is good, or use namespaces — which is better.

Namespaces

Simply by specifying namespaced: true in your module definition you can have a cleaner, unambiguous way for invoking module’s actions and getters.

As a result things like this.$store.dispatch('loadUserById') becomes this.$store.dispatch('user/loadById') where user is the name of the module.

Similarly for getters— this.$store.getters.getUserInfo becomes this.$store.getters['user/getUser'] . A bit longer but way more explicit and clear.


Sometime later you might encounter a scenario where you feel like multiple instances of the same module could be of use. Not sure what I mean? here is an example:

Suppose you have a user module. The user module contains actions for fetching a user, changing his password, updating his preferences etc.

But what happens when as an admin, you are both a user and want to edit another user? This probably means you need to have one instance of the user module pointing to you and another one pointing to the user you want to edit which you’ve selected from a list of users, for example.

A good approach for implementing this would be to register two separate instances of the user module dynamically, as part of the parent component.

Dynamic module registration

This is how we might have solved the scenario above:

Now we can get the info of the logged in user by executing this.$store.getters['currentUser/getFirstName'] and the info of the currently selected user by executing this.$store.getters['selectedUser/getFirstName'] — very convenient!

A small upgrade we might want to consider is to check for the existence of the module before registering it:

and the same approach for UserInfo.vue mentioned before.

But wait, doesn’t that mean having the same method registerStoreModule in every component requiring a dynamically registered module? No, we can do even better by registering a simple mixin. Here it is:

RegisterStoreModule.js mixin

And this is how we use it:

The final cool thing I want to mention is that you can also accept the moduleName as a prop of any given component so you can have variable dynamically-registered components.

A word of caution

If you find yourself registering too many instances of a module — stop to think whether or not this is the correct approach. Components already have their own state which in combinations with props is sometimes good enough, especially for small and utility components.