Pinia Instance
The Pinia instance is the central hub that manages all stores in your application. It's created with createPinia()
and installed as a Vue plugin.
Creating a Pinia Instance
createPinia()
Creates a new Pinia instance.
Signature
function createPinia(): Pinia
Example
import { createPinia } from 'pinia'
import { createApp } from 'vue'
const app = createApp({})
const pinia = createPinia()
app.use(pinia)
Properties
install
- Type:
(app: App, ...options: any[]) => any
Vue plugin install function. Automatically called when using app.use(pinia)
.
state
- Type:
Ref<Record<string, StateTree>>
- Read only
Reactive object containing the state of all stores. Mainly used internally and for devtools.
const pinia = createPinia()
console.log(pinia.state.value) // { user: { ... }, cart: { ... } }
Methods
use()
Adds a plugin to the Pinia instance. Plugins are applied to all stores created after the plugin is added.
Signature
use(plugin: PiniaPlugin): Pinia
Parameters
- plugin: A function that receives a context object and optionally returns properties to add to stores
Example
import { createPinia } from 'pinia'
const pinia = createPinia()
// Add a simple plugin
pinia.use(({ store }) => {
store.hello = 'world'
})
// Add a plugin with options
function createLoggerPlugin(options = {}) {
return ({ store }) => {
if (options.enabled) {
store.$onAction(({ name, args }) => {
console.log(`Action ${name} called with:`, args)
})
}
}
}
pinia.use(createLoggerPlugin({ enabled: true }))
_s
(Internal)
- Type:
Map<string, StoreGeneric>
- Internal use only
Map containing all registered stores. Used internally by Pinia.
_e
(Internal)
- Type:
EffectScope
- Internal use only
Effect scope for the Pinia instance. Used internally for cleanup.
Plugin System
Plugin Context
When creating a plugin, you receive a context object with the following properties:
interface PiniaPluginContext {
pinia: Pinia
app: App
store: Store
options: DefineStoreOptions
}
Properties
- pinia: The Pinia instance
- app: The Vue application instance (Vue 3 only)
- store: The store being augmented
- options: The options object passed to
defineStore()
Plugin Examples
Simple Property Plugin
function addSecretPlugin() {
return { secret: 'the cake is a lie' }
}
pinia.use(addSecretPlugin)
Router Plugin
import { markRaw } from 'vue'
import { router } from './router'
function routerPlugin({ store }) {
store.router = markRaw(router)
}
pinia.use(routerPlugin)
Persistence Plugin
import { watch } from 'vue'
function persistencePlugin({ store }) {
const storageKey = `pinia-${store.$id}`
// Restore from localStorage
const saved = localStorage.getItem(storageKey)
if (saved) {
store.$patch(JSON.parse(saved))
}
// Save to localStorage on changes
watch(
() => store.$state,
(state) => {
localStorage.setItem(storageKey, JSON.stringify(state))
},
{ deep: true }
)
}
pinia.use(persistencePlugin)
TypeScript
Typing Plugins
import type { PiniaPluginContext } from 'pinia'
function myPlugin(context: PiniaPluginContext) {
// Plugin implementation
}
Extending Store Properties
When adding properties to stores via plugins, extend the PiniaCustomProperties
interface:
import 'pinia'
declare module 'pinia' {
export interface PiniaCustomProperties {
router: Router
secret: string
}
}
Extending Store State
For state properties, extend PiniaCustomStateProperties
:
import 'pinia'
declare module 'pinia' {
export interface PiniaCustomStateProperties<S> {
lastUpdated: Date
}
}
SSR Support
Server-Side
// server.js
import { createPinia } from 'pinia'
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp({})
const pinia = createPinia()
app.use(pinia)
return { app, pinia }
}
Client-Side Hydration
// client.js
import { createApp } from './main'
const { app, pinia } = createApp()
// Hydrate state from server
if (window.__PINIA_STATE__) {
pinia.state.value = window.__PINIA_STATE__
}
app.mount('#app')
Testing
Creating Test Instances
import { createPinia, setActivePinia } from 'pinia'
import { beforeEach } from 'vitest'
beforeEach(() => {
const pinia = createPinia()
setActivePinia(pinia)
})
Mocking Plugins
import { createPinia } from 'pinia'
const pinia = createPinia()
// Mock plugin for testing
pinia.use(() => ({
$api: {
get: vi.fn(),
post: vi.fn()
}
}))
Best Practices
Plugin Order
const pinia = createPinia()
// Add plugins in order of dependency
pinia.use(routerPlugin) // Base functionality
pinia.use(persistencePlugin) // Depends on state
pinia.use(loggerPlugin) // Should be last for complete logging
Conditional Plugins
const pinia = createPinia()
// Development-only plugins
if (process.env.NODE_ENV === 'development') {
pinia.use(loggerPlugin)
pinia.use(devtoolsPlugin)
}
// Production-only plugins
if (process.env.NODE_ENV === 'production') {
pinia.use(analyticsPlugin)
}
Plugin Configuration
// Create configurable plugins
function createApiPlugin(baseURL) {
return ({ store }) => {
store.$api = createApiClient(baseURL)
}
}
const pinia = createPinia()
pinia.use(createApiPlugin('https://api.example.com'))
Lifecycle
Installation
createPinia()
creates a new instanceapp.use(pinia)
installs the plugin- Pinia sets up global properties and provides the instance
Store Creation
defineStore()
registers store definition- First call to
useStore()
creates the store instance - Plugins are applied to the new store
- Store is added to the Pinia instance
Cleanup
- When the app unmounts, Pinia cleans up all stores
- Effect scopes are disposed
- Subscriptions are removed
See Also
- createPinia() - Creating Pinia instances
- Store Instance - Store instance API
- Utilities - Utility functions
- Plugins Guide - Plugin development guide