Update State Management with Pinia

Dusko Peric
SMG Real Estate Engineering Blog
3 min readMar 21, 2024

In the development and maintenance of web applications, one of the crucial factors is the proper choice of state management. When it comes to Vue.js, we have two players in the game, where in my opinion, we have a clear winner. In this article, I will go through the functionalities brought by Pinia, which represent a step forward in this field.

Intuitive API

One of the problems in working with state is that it can very easily become confusing and complex. With its component-like structure, Pinia allows for easier understanding of how the store functions and interacts with your application. Let’s look at an example to compare a Vue component with a Pinia store.

Syntax similarity between Vue component and Pinia store

This familiar syntax makes it a user-friendly and efficient solution for managing state.

Excluding Mutations

One of the key differences between Pinia and Vuex lies in the absence of mutations. In Vuex, the distinction between actions and mutations can become less clear-cut, particularly for complex stores. This redundancy can lead to repetitive code, adding unnecessary complexity to state management.

Pinia takes a more direct approach. You can simply modify the state directly within actions. Let’s see a code example to illustrate this concept:

Vuex Store

import { createStore } from 'vuex';

export default createStore({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++; // Update state through mutation
},
},
actions: {
increment({ commit }) {
commit('increment'); // Dispatch mutation to update state
},
},
});

Pinia Store

import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++; // Directly update state within action
},
},
});

In essence, Pinia removes an unnecessary layer of complexity by allowing direct state updates within actions.

Modular stores design

Pinia allow you to create multiple stores for different parts of your application, each of them should be in their own file, which will help keep code organized. Also is posibile sharing state, actions and getters via nested stores.

This modularity allows for independent development and testing.

Flexibility

Pinia offers two main approaches to define stores: Option Stores and Setup Stores.

While Option Stores resemble Vue’s options API, Setup Stores leverage the power of the Composition API for more flexibility.

Option Store

import { defineStore } from 'pinia';

export const useShoppingCart = defineStore('shoppingCart', {
state: () => ({
items: [],
}),
actions: {
addItem(item) {
this.items.push(item);
},
},
getters: {
totalItems() {
return this.items.length;
},
},
});

Setup Store:

import { defineStore } from 'pinia';

export const useShoppingCart = defineStore('shoppingCart', () => {
const items = ref([]);

const addItem = (item) => {
items.value.push(item);
};

const totalItems = computed(() => items.value.length);

return { items, addItem, totalItems };
});

Choose the type of store that feels right to you and your use cases.

Summary

What’s also worth mentioning is that Pinia has built-in TypeScript support and also supports Vue Devtools, which significantly simplifies debugging. Its lightweight nature (around 1.5kb) ensures minimal impact on your application’s performance.

Pinia offers a refreshing alternative for Vue state management, with its focus on simplicity, flexibility, and developer experience. Dive into Pinia and discover its potential to elevate your next project!

--

--