vuejs/pinia pinia
Intuitive, type safe and flexible Store for Vue
Version: 3.0.4 (Nov 2025) Deps: @vue/devtools-api@^7.7.7 Tags: next: 2.0.0-rc.10 (Sep 2021), beta: 2.1.8-beta.0 (Apr 2024), latest: 3.0.4 (Nov 2025)
References: Docs — API reference, guides
API Changes
This section documents version-specific API changes — prioritize recent major/minor releases.
-
BREAKING:
defineStore({ id: 'storeName', ... })— object signature withidproperty removed in v3.0.0; usedefineStore('storeName', { ... })instead. Old object syntax silently compiled but is now a runtime error source -
BREAKING:
PiniaStorePlugintype — removed in v3.0.0; usePiniaPlugininstead. Code usingPiniaStorePluginwill fail to compile source -
BREAKING: Vue 2 support dropped in v3.0.0 — Pinia v3 requires Vue 3 only. Users on Vue 2 must stay on Pinia v2 source
-
BREAKING: TypeScript 5 or newer required in v3.0.0 — uses native
Awaitedtype introduced in TS 4.5; TS 5+ recommended source -
BREAKING: IIFE bundle no longer bundles Vue Devtools in v3.0.0 — devtools API was too large; must be included manually depending on your workflow source
-
BREAKING: Package is now published as
type: modulein v3.0.0 — CJS dist files still provided but the package root is ESM. May break setups relying on implicit CJS resolution source -
NEW:
action(fn, name?)helper in setup stores — added in v2.2.0, available viaSetupStoreHelpersparameter. Wraps a function so it is tracked by$onActionwhen called within the store; intended for advanced use cases like Pinia Colada source -
NEW:
disposePinia(pinia)— added in v2.1.7, stops the pinia effect scope and removes state, plugins, and stores. Useful in tests or multi-pinia apps; disposed instance cannot be reused source -
NEW:
SetupStoreDefinition<Id, SS>type — added in v2.1.7 for the return type ofdefineStore()when using a setup function. ExtendsStoreDefinitionand enables better IDE support for setup stores source -
NEW:
mapWritableStatenow picks up writablecomputeds in setup stores — added in v2.3.0. Previously onlyrefstate was mapped;WritableComputedRefreturns from setup stores are now included source
Also changed: mapGetters DEPRECATED (alias for mapState, still exported) · getActivePinia() returns Pinia | undefined (typed more strictly since v2.0.35) · skipHydrate(obj) stable — skips SSR hydration for non-state objects returned from setup stores · shouldHydrate(obj) exported utility for plugin authors
Best Practices
-
Use
$patch()with a function callback rather than an object when mutating arrays or performing multiple related changes — the function form groups all mutations into a single devtools entry and avoids creating intermediate collections source -
Use
$subscribe()instead ofwatch()on store state — subscriptions fire only once per$patchcall regardless of how many individual properties changed, avoiding redundant callbacks when using the function form of$patchsource -
Pass
{ detached: true }to$subscribe()andtrueas the second arg to$onAction()when you need listeners to outlive the component — by default both are automatically removed on component unmount source -
In setup stores, use
skipHydrate()to wrap state properties that must not be picked up from SSR initial state (e.g., composables backed bylocalStorage, client-only refs) — without it, the server's serialized value will override the intended client-side source source
return {
lastColor: skipHydrate(lastColor), // won't be overwritten by SSR state
open,
}
-
When a plugin adds new state properties, set the value on both
store.$state(for SSR serialization and devtools) andstoreviatoRef(store.$state, 'key')— setting only one breaks devtools display or reactivity sharing source -
Wrap non-reactive external objects (router, class instances, third-party lib instances) with
markRaw()before assigning them in plugins — prevents Vue from trying to deeply observe objects that aren't meant to be reactive source -
When composing stores that reference each other, place
useOtherStore()calls before anyawaitin async actions — after anawaitthe active pinia context may have changed, causing the wrong instance to be returned in SSR source -
Use
createTestingPinia()from@pinia/testingfor component tests rather thancreatePinia()— it stubs all actions by default and makes them inspectable as spies; pass plugins via thepluginsoption, not viatestingPinia.use()source -
In options store getters, prefer arrow functions that receive
stateas the first parameter over regular functions usingthis— arrow function return types are inferred automatically, whilethis-based getters require an explicit return type annotation source