What is Pinia?
By now, you’ve probably heard that Pinia is the officially recognized state management library for Vue.js. Evan You even referred to it as the de facto Vuex 5. But do you know why you should be using Pinia over Vuex and how to use Pinia? In this article, we’ll explain why, in the fight between Vuex vs Pinia, Pinia is the clear winner for your Vue app’s state management. But first, let’s set some groundwork and answer some common questions.
Who created Pinia?
Pinia was created by Eduardo San Martin Morote, the same Vue Core Team member who created Vue Router.
Does Pinia work with Vue 2 and Vue 3?
Yes, Pinia is compatible with both major versions of the Vue.js framework.
How does Pinia compare to Vuex?
Now let’s take a look at some of Pinia’s most exciting features, which make it a better choice over Vuex.
1. Pinia has a Simpler API than Vuex
Pinia’s API is simpler and more intuitive than Vuex. Getting started with state management is much easier even for a junior developer as a lot of boilerplate code that needed to be written between every state change in Vuex has now been removed in Pinia.
A Pinia example
Let’s take a look at a Pinia example. To set up and install Pinia in your Vue app, simply run the following command in your terminal:
yarn add pinia
# or with npm
npm install pinia
Update your main.js
to use Pinia:
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
const app = createApp(App);
app.use(createPinia());
app.mount("#app");
Create a stores
folder under src
and create a file called counter.js
and paste in the following code:
📁src/stores/counter.js
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => {
return { count: 0 };
},
actions: {
increment(value = 1) {
this.count += value;
},
},
getters: {
doubleCount: (state) => {
return state.count * 2;
},
doublePlusOne() {
return this.doubleCount + 1
},
},
});
A few things to note from the code above:
- Mutations have been removed entirely from the state management cycle. Pinia state can directly be updated in our Actions, thereby reducing verbosity
- Pinia Actions no longer need extra arguments such as “context”. You can also subscribe to actions to observe their outcome with
store.$onAction()
- Pinia Getters that rely on other getters to work (i.e
doublePlusOne
relying ondoubleCount
) can get access to the whole store instance usingthis
. However, when using Pinia with TypeScript, it is necessary to define the type of the return due to a known TS limitation, which doesn’t affect getters defined with an arrow function, nor getters not usingthis
.
These changes make our Pinia code much simpler to read and understand when compared to its Vuex counterpart.
2. Pinia is modular by design
Vuex provides you with just one store which can have multiple modules within it. Whereas in Pinia, you can create multiple stores that can be imported into components directly where they’re needed. This allows bundlers to better code split and provides better TypeScript inferences.
Having multiple stores instead of just one also simplifies development, since only the methods of the Pinia Store (or module) need to be used each time, rather than the entire store in Vuex.
Using the Pinia example described earlier, within a single file component, would look something like this:
<script setup>
import { useCounterStore } from "./stores/counter";
const store = useCounterStore();
</script>
<template>
<h1>Count is {{ store.count }}</h1>
<h2>Double is {{ store.doubleCount }}</h2>
<button @click="store.increment()">Increment</button>
</template>
3. Pinia comes with Devtools
If you’re familiar with Vuex, you’ve likely made great use of the Vuex tab of the Vue DevTools. You might even be aware that the separation of Vuex Actions and Mutations meant that the Mutations were what the DevTools hooked into in order to track state changes in Vuex. This might lead you to wonder: Does Pinia have devtools?
Fortunately, the answer is yes. The Pinia devtools are just as helpful as the Vuex devtools you’re already familiar with, and they come out-of-the-box once you’ve installed Pinia in your Vue app.
4. Pinia has built-in Typescript support
Getting Vuex to support types had always been a painful experience for Vue developers. Pinia is a fully typed state management library that eliminates this problem. Type safety adds a lot of benefits to your application such as preventing potential runtime errors, but even if you’re not developing your application in TypeScript, you’ll get other great benefits, thanks to Pinia’s redesigned developer experience, such as auto-completion and auto-suggestion.
To leverage these features, it is recommended that you use arrow functions when defining your state, which will get you the best type inference possible in Pinia.
Pinia’s TypeScript support means you can do things like set up an interface for your state, natively integrate type definitions within Pinia Actions, and get automatic documentation for what arguments the Actions take, complete with auto-suggestion and completion.
Example Pinia with TypeScript store:
interface ToDoItem {
item: string;
id: number;
done: boolean;
}
export const useTodoStore = defineStore('ToDoStore', {
state: () => ({
todos:[] as ToDoItem[]
}),
actions: {
addTodo(item: string) {
this.todos.push({ item, id: this.id++, done: false })
}
}
})
Should I use Pinia or Vuex?
Although Pinia has been recognized as the official state management solution for Vue apps moving forward, that does not mean Vuex has been deprecated. If you have an app in production already using Vuex, your application will still work fine and it’s recommended that you continue to use Vuex since migrating from one library to another can be a lot of work.
However, if your project is still in its early development phases, Pinia is the way to go. You’ll benefit from Pinia’s easier-to-understand syntax and simplicity among the other features covered in this article.
If you would like to find out how to migrate from Vuex to Pinia, check out this course taught by Vue Core Team Member Ben Hong. You can also watch this informative Q&A session with Eduardo San Martin (creator of Pinia) where he answers some really interesting questions about Pinia and state management in general. He also demonstrates, in a live tutorial, how you can persist state in Pinia using local storage with the useLocalStorage
composable from VueUse.
Pinia is quickly solidifying its place in the Vue community, and we think these courses are the best way to get started with Pinia.