Skip to content

What is Pinia?

Pinia is a store library for Vue.js that allows you to share state across components and pages. It's the official state management solution for Vue.js and serves as a replacement for Vuex.

Key Features

💡 Intuitive

Stores are as familiar as components. The API is designed to let you write well-organized stores with minimal boilerplate.

🔑 Type Safe

Types are inferred automatically, which means stores provide you with autocompletion even in JavaScript! Full TypeScript support out of the box.

⚙️ Devtools Support

Pinia hooks into Vue devtools to give you an enhanced development experience with:

  • Timeline to track actions and mutations
  • Stores appear in components where they are used
  • Time travel debugging

🔌 Extensible

React to store changes and actions to extend Pinia with:

  • Transactions
  • Local storage synchronization
  • Custom plugins

🏗 Modular by Design

Build multiple stores and let your bundler code split them automatically. Each store is independent and can be imported only when needed.

📦 Extremely Light

Pinia weighs around 1.5kb (min+gzip), making it one of the lightest state management solutions available.

Comparison with Vuex

Pinia offers several advantages over Vuex:

FeaturePiniaVuex
TypeScript Support✅ Excellent⚠️ Requires complex setup
Devtools✅ Built-in✅ Built-in
Mutations❌ Not needed✅ Required
Actions✅ Sync & Async✅ Async only
Modules✅ Multiple stores✅ Nested modules
Bundle Size📦 ~1.5kb📦 ~2.5kb
Learning Curve📈 Gentle📈 Steep

When to Use Pinia

Pinia is perfect when you need to:

  • Share state between multiple components
  • Manage complex application state that goes beyond simple prop passing
  • Implement global state that persists across route changes
  • Handle server-side rendering with proper state hydration
  • Debug state changes with time-travel debugging
  • Extend functionality with plugins

Basic Concepts

Pinia is built around three main concepts:

Store

A store is a container that holds your application state, getters, and actions. Think of it as a component that you can use anywhere in your app.

State

The data of your store. It's reactive and can be accessed from any component.

Getters

Computed values based on the store state. They're cached and only re-evaluate when their dependencies change.

Actions

Functions that can modify the state. They can be synchronous or asynchronous.

Example

Here's a simple counter store to give you a taste of Pinia:

js
// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  
  getters: {
    doubleCount: (state) => state.count * 2
  },
  
  actions: {
    increment() {
      this.count++
    },
    
    async fetchCount() {
      const response = await fetch('/api/count')
      this.count = await response.json()
    }
  }
})
vue
<!-- Component.vue -->
<template>
  <div>
    <p>Count: {{ counter.count }}</p>
    <p>Double: {{ counter.doubleCount }}</p>
    <button @click="counter.increment()">+1</button>
  </div>
</template>

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

const counter = useCounterStore()
</script>

Ready to get started? Let's move on to Getting Started!

Released under the MIT License.