Linn Linn Htun
Linn Linn Htun
AvatarLinn Linn Htun

Pinia

August 21, 2023

Pinia

Pinia is the officially recommended state management library for Vue 3, designed to replace Vuex with a simpler, more intuitive API and first-class TypeScript support. This post covers how to set up Pinia, define stores with state, getters, and actions, how Pinia compares to Vuex, and practical patterns for managing global state in Vue applications.

Pinia

Pinia is a library for storing data in a central location. You won't have to pass it down from component to component. The state is directly accessible to all components. It doesn't matter how deeply nested your components are, the data can be retrieved or updated. Any changes to the data are reflected in all components. This means it's no longer necessary to pass down data through several children components. Data is handled in one centralized location. 

Pinia is maintained by the core developers of Vue. You don't have to worry about compatibility issues. 

npm install pinia

What is Pinia doing behind the scenes?

Pinia is registering a plugin with the Vue developer tools. The developer tools are completely extendable. The Pinia package will add a new tool for interacting with the state. If you want help with debugging, you should always register the plugin. 

 

Working with State

Let's create a sample js file called modal.js. And then import defineStore function from the pinia package 

import { defineStore } from "pinia";

defineStore function will help us create a new store. We can think of the store as an object that will track the data store inside it. store must be exported from the file, otherwise our components will not have access to the data. 

export default defineStore();

inside defineStore function, we can define state id with object like below:

export default defineStore("modal", {
 
});

In object we can add various properties for interacting with our state. Let's add state property 

export default defineStore("modal", {
state: () => ({
isOpen: false,
})
});

The state object is where we can add our data. Any data we want globally available to other components should be defined here.

We can access the state in another component:

in Header.vue

<script>
import { mapStores } from 'pinia'
</script>

mapStores function will merge the store into the component, thus giving us access to the state. 

And the import our store file also:

<script>
import { mapStores } from 'pinia';
import useModalStore from '@/stores/modal';

export default {
computed: {
...mapStores(useModalStore);
}
}
</script>

And then we can access state value:

<script>
import { mapStores } from 'pinia';
import useModalStore from '@/stores/modal';

export default {
computed: {
...mapStores(useModalStore);
},
methods: {
toggleAuthModal() {
this.modalStore.isOpen = !this.modalStore.isOpen;
}
}
}
</script>

As we can access state value by using this.modalStore. Because we created modal state property. For example, if we create user state then we can access this.userStore 

 

Using Getters

There is a way to change a state property inside the store. Just like we can create mutations, we can create something called getters. Getter are exactly what they sound like. They allow you to access a state property from the store.  Using a getter is optional. We can access the state property directly through the store object. Pinia offers another solution for retrieving a state property called getters. 

The main benefit of using a getter is the support for caching. It can intelligently update itself when the state changes. We know that the computed properties are one way to cache a value. One solution might be to write a computed property for every state property we'd like to use in a given component, that would work. But then we would face duplication issues. 

We'd have to define the same computed properties in every component. That's where getters come in. We can think of getters as computed property for our store. One of the main benefits of a getter is that they're accessible to all components. Define a getter once, use it everywhere. Getters are also smart. They will only update if the state changes. This can help with the performance of an application. 

in modal.js

import { defineStore } from "pinia";
export default defineStore("modal", {
state: () => ({
isOpen: false,
}),
getters: {
hiddenClass(state) {
return !state.isOpen ? 'hidden' : '';
}
}
});

in Example.vue

<script>
import { mapStores } from 'pinia';
import useModalStore from '@/stores/modal';

export default {
computed: {
...mapStores(useModalStore, ["hiddenClass"]);
}
}
</script>
<div id="modal" :class="hiddenClass"></div>

 

 

 

Frequently Asked Questions

What is Pinia?

Pinia is the official state management library for Vue, offering a lightweight alternative to Vuex with a more intuitive API, full TypeScript support without configuration, hot module replacement for stores, and excellent Vue DevTools integration.

What is the difference between Pinia and Vuex?

Pinia has a simpler API with no mutations (only state, getters, and actions), better TypeScript support out of the box, support for multiple stores without nesting, and is the officially recommended choice for new Vue 3 projects over Vuex.