Things are a-changing in the Vueniverse - as are our approaches to state management. In the past, Vuex was the default choice for state management (though not always the most loved one). Now you’ll see other solutions being recommended.
Vue 3 simplifies a lot of things, and new solutions are great. But we know it can get confusing to keep up with best practices. What to (not) use now?
An alternative title for this article was „Vue 3 state management for dummies“. We know you’re not a dummy, but consider this your executive summary of current state management concepts and resources for Vue 3.
To display an app’s interface, you need a lot of information about its state: Should this checkbox be checked? Was that form submission successful?
When the user interacts with the app, this state information often needs to be used by multiple different components. Think about a user putting a product into their shopping cart in an e-commerce app: This state probably needs to be reflected on the product page („added to cart!“) and in the cart components (changed product count in the cart and added product in the list).
Saving and accessing this data in a centralized, structured way (instead of passing it around from one component to another) is what we typically mean when we talk about state management.
The store we use for this is sometimes likened to a frontend database. It makes sure you have only one single source of truth for the data. You can access it from everywhere to use in different contexts. Easier to work with, easier to maintain, less bug-prone!
Whether you need a state management solution depends on the complexity and structure of your app. It's not really about its size, but larger apps tend to grow more complex as well. Do multiple of your components need to react and change when a user interacts with your app? That’s a good indicator that you should think about state management.
Before we get into libraries you can use to manage your application's state: Do we even need a dedicated state management library with Vue 3? An intensely discussed topic these days!
As Vue matured, it got progressively easier to manage state without a state management library. With the introduction of Vue Observables in Vue 2.6, we already could set up a homemade store by creating a reactive object that holds our shared application state. Now the Composition API and its globally available reactive objects make it even easier to share state and stateful logic between components.
You can find an example of a simple state management pattern in the Vue 3 docs. Here are some additional tutorials and articles about how you could go about writing your own store:
Creating your own store could be interesting for you if you’re looking for a (really) flexible solution. What you’ll be missing is the possibility to debug your store with Vue Devtools. Also, if you’re deciding on a state management solution for large projects (and teams), you might still prefer the standardization of a state management library.
Pinia went from experimental approach for Vue 3 by core team member Eduardo San Martin Morote to popular library quite fast.
Its name means pineapple in Spanish (piña), which is a nod to the core concept of modular, connected stores – because a pineapple is actually not one fruit, but multiple fruits merged together. (Did you know?)
The lightweight library (1KB) is straightforward to use, and takes away a lot of the complexity devs dislike about Vuex, the previously officially recommended Vue state management solution. No mutations (functions that are used to change state), no complicated nested structures, automatic namespacing and code splitting, proper TypeScript support. Pinia is fully extensible, so you can create plugins on top of it and it also supports server-side rendering (SSR) and debugging with Vue Devtools.
Pinia has initially been an experiment to test this approach for the development of Vuex 5 (remember, it has been created by a core team member!). As it got so popular, it’s no surprise that this is also the direction Vuex will be going.
Here are some resources to get you started:
Vuex is the state management library officially maintained by the Vue core team. It does not have a reputation of being easy to use, but that’s mainly because of trade-offs needed for being a powerful solution.
Vuex (up to Vuex 4) is the Vue-specific implementation of the Flux design pattern, originally developed by Facebook. Other popular state management libraries are based upon this architecture as well – like Redux, which is technically framework-agnostic but most commonly used together with React. In this pattern, there’s only one centralized way to update values in your store, making sure it can’t be changed directly (and accidentally).
In Vuex (up to Vuex 4), this results in more code and complexity. You kind of trade simplicity for predictability and prevention of accidental state changes. This is a pretty good trade in many cases!
As for more pros: Vuex has flawless Devtools support, including useful features like time travel debugging. It’s also tailored to fit Vue’s reactivity system, supports SSR and code splitting.
Vuex 4 already made some changes to be easier to use compared to previous versions, but it is mostly an update for Vue 3 support while keeping the same API as Vuex 3. More exciting changes are coming with Vuex 5, which is currently an RFC (Request for Comments) proposal.
As you already read above, Vuex 5 will go the same direction as the Pinia state management library, bringing TypeScript support and removing the need to use mutations and nested modules which caused a big chunk of complexity.
This means it’s moving away from being a Flux library for Vue towards being Vue’s own, extensible solution for global state management. (Note that this probably makes migrating from Vuex 3 or 4 to Vuex 5 costly!)
Hear, see and read more about Vuex 5 here:
When things evolve, they sometimes get confusing for a while. So, Pinia and Vuex are the same? Or will be the same? What to use? To make your confusion complete: The official Vue.js default recommendation for state management is now ... Pinia!
As Evan You pointed out, you can consider Pinia to be Vuex 5.
We don't yet know how these libraries will coexist or be merged exactly, but what started out as an experiment is now a popular library that mirrors what Vuex 5 aims to be. Pinia has the same core API as Vuex 5 and aims to stay compatible in any case.
It’s a nice example how things evolve in the community: Sometimes it's great to move fast and create a new library to test an idea like it happened with Pinia – but for officially supported libraries it's also important to involve the community's opinions (e.g. through the RFC process that Vuex uses). With Pinia and Vuex 5, both approaches support the same solution!
If you want to keep tabs on other approaches to state management by the community, you can take a look at these projects as well: