Pinia state management for Vue 3 using Composition API style stores.
Store Definition
- Defining stores with defineStore() → See define-store-composition-api
- Choosing between setup stores and options stores → See setup-vs-options-store
- Organizing store files and directory structure → See store-organization
- Using store composables in components → See store-in-components
- Creating reusable store patterns → See store-composition-patterns
State
- Mutating state directly vs using actions → See state-mutation-best-practices
- Resetting state to initial values → See state-reset-pattern
- Using reactive vs ref for state → See state-reactive-vs-ref
- State persistence with localStorage → See state-persistence
- Deep reactivity with nested objects → See state-deep-reactivity
- State hydration from API → See state-hydration
Getters
- Getters not caching computed values → See getter-computed-caching
- Passing arguments to getters → See getter-pass-arguments
- Accessing other store getters → See getter-cross-store-access
- Getter performance with expensive operations → See getter-performance-optimization
Actions
- Async actions and error handling → See action-async-error-handling
- Calling actions from other stores → See action-cross-store-calls
- Action composition and reusability → See action-composition-patterns
- Batch state updates in actions → See action-batch-updates
- Testing actions with mocked dependencies → See action-testing-strategies
TypeScript
- Typing store state with interfaces → See typescript-state-typing
- Typing getters and actions → See typescript-getters-actions-typing
- Using Pinia with TypeScript generics → See typescript-generic-stores
- Type-safe store composition → See typescript-store-composition
- Type inference for auto-imported stores → See typescript-auto-import-types
Store Composition
- Combining multiple stores → See store-composition
- Avoiding circular dependencies between stores → See store-circular-dependencies
- Shared state across stores → See store-shared-state
- Extracting common store logic → See store-logic-extraction
Best Practices
- Store size and performance → See store-performance-optimization
- When to use Pinia vs provide/inject → See pinia-vs-provide-inject
- Testing Pinia stores → See testing-pinia-stores
- Migrating from Vuex to Pinia → See migrating-from-vuex
Quick Reference
Basic Setup Store (Composition API)
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
function $reset() {
count.value = 0
}
return { count, doubleCount, increment, $reset }
})
Using Store in Component
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double: {{ counter.doubleCount }}</p>
<button @click="counter.increment">Increment</button>
</div>
</template>
Store with TypeScript
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
interface User {
id: number
name: string
email: string
}
export const useUserStore = defineStore('user', () => {
const user = ref<User | null>(null)
const isAuthenticated = computed(() => user.value !== null)
async function login(email: string, password: string) {
const response = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ email, password })
})
user.value = await response.json()
}
function logout() {
user.value = null
}
return { user, isAuthenticated, login, logout }
})
Store Composition
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { useAuthStore } from './auth'
import { useCartStore } from './cart'
export const useCheckoutStore = defineStore('checkout', () => {
const authStore = useAuthStore()
const cartStore = useCartStore()
const isProcessing = ref(false)
async function checkout() {
if (!authStore.isAuthenticated) {
throw new Error('User not authenticated')
}
isProcessing.value = true
try {
await processPayment(cartStore.items)
cartStore.clear()
} finally {
isProcessing.value = false
}
}
return { isProcessing, checkout }
})
Key Imports
// Core
import { defineStore } from 'pinia'
import { createPinia } from 'pinia'
// Vue Composition API (used in setup stores)
import { ref, reactive, computed, watch } from 'vue'
// Store instance
import { storeToRefs } from 'pinia'
// Type utilities
import type { StoreDefinition } from 'pinia'
Installation
npm install pinia
# or
yarn add pinia
# or
pnpm add pinia
Setup in 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')