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:
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
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.
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
user is the name of the module.
Similarly for getters—
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:
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.