Pinia Basics
Pinia is Vue's official state management library, replacing Vuex as the recommended solution for sharing state across unrelated parts of a component tree. A Pinia store is a self-contained unit holding state, computed getters, and actions that mutate that state, and it integrates directly with Vue's reactivity system — meaning a store's state behaves just like a ref or reactive object when accessed from a component. Pinia is intentionally minimal: no mutations boilerplate, full TypeScript inference, and devtools support out of the box.
Cricket analogy: Pinia is like a modern team analytics platform replacing an old paper scorebook (Vuex) — one dashboard holds player stats, computed averages, and substitution actions, updating live the moment a run is scored, with no separate "submit scoresheet" ritual required.
Defining a Store
Stores are created with defineStore(), which needs a unique id string and a setup function that mirrors the Composition API: refs become state, computed values become getters, and plain functions become actions. This 'setup store' style is now the recommended way to write Pinia stores because it looks and feels exactly like writing a component's <script setup> block.
Cricket analogy: Defining a store with defineStore('cartStore', ...) is like registering a team under a unique squad ID, then writing its playbook exactly like matchday notes — player fitness trackers become state, the computed net run rate becomes a getter, and a "callTimeout" routine becomes an action.
// stores/cart.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCartStore = defineStore('cart', () => {
const items = ref([])
const itemCount = computed(() =>
items.value.reduce((sum, item) => sum + item.qty, 0)
)
function addItem(product) {
items.value.push({ ...product, qty: 1 })
}
function clearCart() {
items.value = []
}
return { items, itemCount, addItem, clearCart }
})Using a Store Inside Components
Any component can import and call the store's use* function to get a reactive instance of it. State and getters are read directly in templates or script, and actions are called like normal functions — no dispatch/commit ceremony like Vuex required.
Cricket analogy: Any player on the field can call useTeamStore() to get the live scoreboard, read the current run rate directly, and call requestReview() like an ordinary shout to the umpire — no formal appeal form required as older review systems demanded.
<script setup>
import { useCartStore } from '@/stores/cart'
const cart = useCartStore()
</script>
<template>
<p>Items in cart: {{ cart.itemCount }}</p>
<button @click="cart.addItem({ id: 1, name: 'Keyboard', price: 79 })">
Add Keyboard
</button>
</template>Pinia requires no module nesting or namespacing the way Vuex did — every store is flat and independently importable, and stores can even use other stores directly inside their setup function (e.g. the cart store calling useAuthStore() to check who's logged in), making cross-store composition straightforward.
Destructuring reactive state directly out of a store, e.g. const { items } = useCartStore(), breaks reactivity just like destructuring any other reactive object. Use storeToRefs(store) to destructure state and getters while keeping their reactive connection; plain actions can be destructured safely since they're just functions.
- Pinia is Vue's official, minimal state management library, replacing Vuex.
- defineStore(id, setup) creates a store; the setup-store style mirrors <script setup> exactly.
- refs become state, computed values become getters, and functions become actions — no mutations needed.
- Components call the store's use* function to get a fully reactive instance to read and act on.
- Stores can call other stores directly, enabling straightforward cross-store composition.
- Destructuring state/getters from a store breaks reactivity; use storeToRefs() to preserve it.
Practice what you learned
1. What library does Pinia replace as Vue's officially recommended state management solution?
2. In the setup-store style of defineStore, what does a ref() declared inside the setup function become?
3. How do components call a store's methods to mutate its state, e.g. adding an item to a cart?
4. What happens if you write const { items } = useCartStore() directly?
5. Can one Pinia store call functions from another store within its own setup function?
Was this page helpful?
You May Also Like
Pinia Actions and Getters
Learn how Pinia actions encapsulate business logic and mutations while getters derive cached, reactive values from store state.
Sharing State Across Components
Compare the tools Vue offers for cross-component state sharing — props/emits, provide/inject, composables, and Pinia — and when to reach for each.
Local Component State Patterns
Explore idiomatic ways to structure a component's own internal reactive state before reaching for external state management like Pinia.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics