f in x
> cd .. / HUB_EDITORIALE
Sviluppo di siti web

Pinia for Vue 3 — Modern State Management That Finally Replaces Vuex

[2026-06-23] Author: Ing. Calogero Bono

Your Vue 3 project is growing. Props are being passed down multiple levels, events are flying between parent and child, and that global reactive variable outside any component is making you nervous. You need centralized state management. The classic choice was Vuex. But with the Composition API, Vuex started showing its age. That's why in 2026 the answer is Pinia.

We at Meteora Web have migrated several projects from Vuex to Pinia — and we're not going back. In this guide, we explain what it is, how to use it, and why it's better. With real examples, not theory.

What is Pinia and why does it replace Vuex?

Pinia is a state management library for Vue 3 created by Eduardo San Martin Morote, the same author of the Vuex module. It's not an alternative: it's the official heir. Natively integrated with Vue DevTools, it supports Composition API from day one, and eliminates all the verbosity of Vuex (mutations, forced namespacing, nested stores).

The key difference? Pinia has no mutations. You act directly on the state through actions, which can be synchronous or asynchronous. TypeScript is first-class. And the structure is flat: each store is an independent module, no need for 'namespaced: true' like in Vuex.

Why we left Vuex behind

Vuex was built for Vue 2, with object-based options syntax. With Vue 3 and Composition API, you could use it but it felt like a hybrid. Pinia was designed for Vue 3 and integrates perfectly with the Composition API. If you want to dive into Vue 3 basics, check our guide on Vue.js 3 and Composition API.

Sponsored Protocol

How to install and configure Pinia in a Vue 3 project?

Installation is one command. Then register the plugin in your main app.

npm install pinia
# or
yarn add pinia
// main.js / main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.mount('#app')

Done. Now you can create stores anywhere. Pinia uses a singleton pattern: once created, a store is reused automatically.

How to define a store with Pinia and the Composition API?

There are two ways: setup store (our favourite) or Options API. Here's the Composition API style, which is more flexible and integrates seamlessly with the rest of your code.

// stores/counter.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useCounterStore = defineStore('counter', () => {
  // State
  const count = ref(0)
  
  // Getters (derived state)
  const doubleCount = computed(() => count.value * 2)
  
  // Actions
  function increment() {
    count.value++
  }
  
  async function fetchAndSet() {
    const response = await fetch('/api/count')
    const data = await response.json()
    count.value = data.value
  }
  
  return { count, doubleCount, increment, fetchAndSet }
})

Note the syntax: defineStore takes two arguments — a unique store name and a setup function. Inside, use ref for state, computed for getters, and regular functions for actions. Everything you return will be accessible from the component.

Sponsored Protocol

How to use the store in a Vue 3 component?

Simple: call the composable useCounterStore inside setup() or <script setup>.

<script setup>
import { useCounterStore } from '@/stores/counter'

const store = useCounterStore()
</script>

<template>
  <div>
    <p>Count: {{ store.count }}</p>
    <p>Double: {{ store.doubleCount }}</p>
    <button @click="store.increment()">+</button>
  </div>
</template>

No mapState or mapActions. The store object is reactive and you can access it directly. Be careful: to keep reactivity when destructuring, use storeToRefs.

import { storeToRefs } from 'pinia'
const { count, doubleCount } = storeToRefs(store)
// count and doubleCount are ReF, not plain values
const { increment } = store // actions can be destructured freely

How to handle async actions and API calls with Pinia?

One of Pinia's strengths is that actions can be async without extra configuration. In our example fetchAndSet is already an async action. Call it directly from the component as store.fetchAndSet(). No mutations, no commits: set the state directly, and the UI updates automatically. This cuts boilerplate by 50% compared to Vuex.

Sponsored Protocol

Does Pinia support TypeScript better than Vuex?

Absolutely. Pinia is written in TypeScript and provides automatic type inference. If you define the store with a setup function, types for parameters and return values are deduced without extra interfaces. In Vuex you had to manually declare types for state, getters, mutations. With Pinia, defineStore returns a typed composable — use it in TypeScript components and enjoy autocompletion and compile-time checks.

// counter.ts
interface CounterState {
  count: number
}

export const useCounterStore = defineStore('counter', () => {
  const count = ref<number>(0)
  // ...
})

TypeScript works out of the box. For a practical example of TypeScript integration with Vue 3, see our page on Vue.js 3 and Composition API.

How to persist Pinia state (localStorage, sessionStorage)?

Pinia doesn't include a persistence plugin in core, but the ecosystem provides one. The most popular is pinia-plugin-persistedstate. Install and configure once.

npm install pinia-plugin-persistedstate
// main.js
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

Then in your store, add persist: true:

Sponsored Protocol

export const useAuthStore = defineStore('auth', {
  state: () => ({ token: null }),
  persist: true, // saves to localStorage automatically
  // ...
})
// Or with setup store:
export const useAuthStore = defineStore('auth', () => {
  const token = ref(null)
  return { token }
}, { persist: true })

You can customize the key, storage, and serialization. For simple projects, it's enough.

What are common mistakes when migrating from Vuex to Pinia?

The most common? Destructuring the store without using storeToRefs. Vuex returned reactive objects, but with Pinia if you do const { count } = store, you lose reactivity. Always use storeToRefs for state and getters. Actions can be destructured freely.

Second mistake: forgetting that Pinia has no mutations. Don't try store.$commit() — it doesn't exist. You modify state directly. That's simpler but requires discipline: are mutations logged in DevTools? Yes. Pinia tracks every state change, even direct ones. So debugging is identical.

Third mistake: creating too many stores when one would do. Each store is a module, but don't multiply them without reason. An e-commerce store will have one for cart, one for user, one for catalog. Not one per page.

Sponsored Protocol

Pinia vs Vuex — which to choose for a new Vue 3 project in 2026?

No contest. For a new Vue 3 project, the choice is Pinia. Vuex is in maintenance mode, no new features. The official Vue documentation recommends Pinia for all new projects. If you have an existing Vuex project, consider migrating: Pinia provides a migration guide (see official migration page).

We at Meteora Web have done it several times. The switch is painless: often you keep the same state structure, replace mutations with actions, remove namespacing. The code becomes more readable and the bundle smaller (Pinia ~1KB, Vuex ~5KB).

What to do now

  1. Install Pinia in an existing or new Vue 3 project: npm install pinia.
  2. Create your first store with defineStore and a setup function. Use ref for state, computed for getters, functions for actions.
  3. Use the store in a component with useXStore() and storeToRefs if needed.
  4. Add persistence with pinia-plugin-persistedstate if you have data to save (tokens, user preferences).
  5. Read the official docs at pinia.vuejs.org — clear and well-structured.

If you have an existing Vuex project, consider migrating. If starting from scratch, don't look back. Pinia is the right tool for modern, clean, performant state management in Vue 3.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // DIGITAL AGENCY

We build the digital presence your business deserves.

Websites, social media, online advertising, e-commerce and high-performance hosting, engineered with method by computer engineers in Sciacca, for all of Italy.

> MW_JOURNAL

> READ_ALL()