Vuex! Our state management hero for Vue.
In this guide, we’re going to explain the concepts of state management in Vue, what is Vuex, the basics of it works.
After this, you’ll be ready to integrate Vuex into a new or existing Vue App!
As our requirements grow for our applications, they become increasingly complex, managing the state in an appropriate way is a big part of this complexity problem that can be quickly made easier using Vuex.
We’re going to assume you’re familiar with Vue already, if not, get yourself up to scratch with the basics here: https://vuejs.org/v2/guide
What is State Management?
State management is simply the way you handle your application state and data. There are certain patterns you can adhere to for better managing data and state across your application. Sometimes, this also is wrapped up in a library (like Vuex!) that will help you implement it.
In Vue, you’ll already be familiar with managing the application state at a basic level, you do this most the time by passing data to components via Props and emitting and catching Events across your App. This is everyday Vue stuff. However, for anything larger than an “advanced todo list” App (or a medium-to-large scale application in Vue), you’ll most likely come across some questionable decisions and repetition you’ve had to make in the way your handling the state of data shared across your App and advanced Components.
What is Vuex?
A great explanation taken from the official Vuex docs itself;
“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.”
What does it solve?
An example of how quickly things can spiral out of control is a shopping cart in Vue. In standard Vue, you’d probably end up manually emitting or passing data via props for our cart data changes to multiple components across our application (eg, header, product page, wishlist, cart page) Manually write some code to then catch these events if required and to update our local data for that component and let Vue render it again, displaying the updated cart contents/quantities/pricing etc. That’s a lot of important data to keep up to date across multiple places. Sometimes even passing data via Props isn’t an option, as some applications can be structured in all sorts of ways, so sometimes relying on mainly emitting events with your data as your single source of truth which isn’t great at all. 👎
The more components you have, the more complex the interactions between these and the data it may share becomes inefficient and messy very quickly.
Vuex to the rescue 👍
Vuex helps by giving you an entire library (or system) you can use to easily keep the state/data of your application consistent and accessible easily through all of your components while ensuring updates to it are predictable through “mutations”
Using Vuex does complicate your application a little bit though – but in a good way! It’s a trade-off that you’ll have to deal with initially. Speed vs Complexity. It will slow you down at the start, but once you’ve got your head around its concepts and how it works, this slowdown is suddenly made up by all the help and stability it provides for your application. This helps prevent many of the issues of inconsistency in data and state that you can find in some larger Vue projects not using Vuex or a decent state management pattern. … So for a better understanding of Vuex, let’s dive in and explain the concepts of Vuex.
How does it work?
We can create a store in Vuex that gives us a place for us to put data, state and information that we want to be accessible across our application, an ideal use for this would be a place to store, a list of “todos”, and their done status for example.
But for demo purposes, let’s stick to an even simpler example, lets setup a basic Vue App and create a simple Vuex store that holds information for a number “count”.
You can install Vuex via the following methods:
npm install vuex --save
yarn add vuexarn
Once that’s done, you can import it and let Vue know we’re going to use it in this application:
Note: If you use Vue/Vuex via the CDN you can skip this import step.
For more in depth installation instructions see: https://vuex.vuejs.org/installation.html
import Vue from 'vue'
import Vuex from 'vuex'
Let’s create our basic Vue application and Vuex store.
Inside our application we can easily read from this store by calling the state, the state is an instance of the store that is shared across your entire application. This is a singleton, so we can read from this state in any of our components and always retrieve the same up to date information. This is all without even touching a prop or passing our data via an emitted event like we’d previously have to. Changes to the state are also out the box reactive in Vue, so all of your templates will automatically update and re-render when something in the state changes that it is using. Handy!
Now we’re going to pull in the count from the state so we can use it render it in our template.
You can change the state by “committing” Mutations, this is a pattern that the Vuex library implements and is strictly the only way to change the state. Mutations are defined on the store declaration itself. They are just functions that will mutate data inside the store. So for example, for a store that holds a counter variable. Two mutations you could create are “increase” and “decrease”. Inside these mutation functions, you would alter the number of the count in the store.
You cannot call mutations directly though, they must be called from within your Vue application and components via a commit. Vuex Commit functionality is exposed for you to use from pretty much anywhere within your application (just like you can access the State from anywhere within your application). You call it like so:
Doing it this way also leaves behind a trail of changes. You can view and interact with these commits in the official Vue Devtools extension. Making debugging incredibly more useful with Vuex when you can see every single change that happens in the state, a lot less guesswork meaning way less stressful debugging. Another hooray for Vuex 🎉!
This isn’t as easy as the traditional way of updating variables and data in Vue, by simply setting it. However, as you can see – It isn’t too difficult either. And is easy enough to allow you to either add this to an existing Vue application or a brand new one. And for larger applications, it’s benefits shines, giving us much more structure, rules, and allows us to do more complex interactions with our state, like queuing up a bunch of commits in an Action (read more here: https://vuex.vuejs.org/guide/actions.html)
We’ve used JSFiddle so for this basic count example vue application so you can quickly try it out yourself, make changes and get to grips with Vuex in the browser. You can fork it and try it out for yorself here: https://jsfiddle.net/ok0197fm/
For an overview of how the flow of interactions happen when using Vuex in your Vue applications, you can use this infographic from Vuex (your developer friends love it when you print and frame infographics like this)
You don’t have to store your entire application state in the Vuex Store. For anything that is going to be accessed across multiple components, to be done so in the Vuex Store. For things that only make sense or will not be shared anywhere else in your application, to be stored locally in that Vue Component. Generally for larger data you’re retrieving in your app, would come from an API/externally and can be intensive to retrieve it from scratch everytime you want to use, it would make sense to be stored in the Vuex Store. Also, most likely there are that parts of this retrieved data that will be accessed from multiple components/routes multiple times, for example, a listing and detail component sharing some of the same data.
And there are a few extra goodies that come along with using Vuex, we’ve mentioned about integration with the official Vue Devtools (Which is a biggie), but it also supports things like Hot (module) Reloading / HMR, it supports testing frameworks like Mocha + Chai, and there are a few nice plugins that are well supported with Vuex, like local-storage integration. So you can close the application window, open it again and persist the data, giving you the same stored vuex state that it was when you closed it.
We’re big fans of Vuex, we use it in some of our Vue projects and are soon going to implement it into our largest Vue application to date, where using advanced functionality like the Modular architecture (splitting stores up into separate files) and using things like Actions will be a brilliant addition.
We recommend trying it in your next Vue application, and chances are, you’ll not look back and find it a great addition to your Vue workflow!