Skip to content

Guide · Open source

How to use Pinia: install, create a store and use it in Vue

Updated · written with AI from the project's own documentation and checked against our catalogue data

Pinia is a state management library for Vue that gives your app one central place to keep shared data, such as a logged-in user or a shopping cart. This guide is for Vue developers who need the same data in several components. By the end you will know how to install Pinia, create a store, and read and change its state from a component.

Piniavuejs/pinia · ★ 14.8k · MIT

Quick start

  1. 1Install Pinia. Run npm install pinia @vue/devtools-api in your Vue 3 project. You can also use pnpm or yarn.
  2. 2Register Pinia. Call createPinia() and pass the instance to app.use() before mounting the app.
  3. 3Create a store file. Create a file such as stores/main.ts and define a store with defineStore and a unique name.
  4. 4Add state, getters and actions. Return initial data from state, derive values with getters, and change data in actions using this.
  5. 5Import the store in a component. Call the useMainStore function inside setup to get the store instance.
  6. 6Extract reactive values. Use storeToRefs to pull out state and getters so they stay reactive in the template.

What Pinia is and when you need it

Pinia keeps shared data in stores. Components can read and change that data directly, without passing values through many layers of props. Stores are defined in separate files and can be used from any component.

If your app has only a few components and no shared state, a plain reactive object may be enough and Pinia adds little. Pinia is built for Vue, and the main version targets Vue 3. For Vue 2, the README points to a separate v2 branch.

  • Good fit: Vue 3 apps with shared state across several components
  • Good fit: TypeScript projects that want store types inferred automatically
  • Good fit: projects using the Composition API or Nuxt (a @pinia/nuxt module is listed)
  • Not a fit: Vue 2 projects, or non-Vue front-end frameworks

Install Pinia in your Vue project

Pinia is installed with a package manager. Your project needs Node.js and a Vue 3 project. The README does not state a required Node.js version, so check the project documentation for that.

The README installs Pinia together with the DevTools API package, which supports inspecting stores in devtools.

npm install pinia @vue/devtools-api

Register Pinia in your app

Create a Pinia instance with createPinia() and pass it to your app with app.use(). Do this before you mount the app.

For Nuxt configuration and more detailed setup, see the Pinia documentation at pinia.vuejs.org.

import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' const pinia = createPinia() const app = createApp(App) app.use(pinia) app.mount('#app')

Create a store with defineStore

A store has a name, state, and optionally getters and actions. The name must be unique across your application, and it appears in devtools. The README suggests putting each store in its own file.

State is a function that returns a fresh state object. Getters are computed values derived from state. Actions are functions that change state, and inside them this refers to the store instance.

  • state: returns the initial data
  • getters: computed values; they receive state as the first parameter
  • actions: functions that change state; use this to reach the store
import { defineStore } from 'pinia' export const useMainStore = defineStore('main', { state: () => ({ counter: 0, name: 'Eduardo', }), getters: { doubleCounter: (state) => state.counter * 2, doubleCounterPlusOne(): number { return this.doubleCounter + 1 }, }, actions: { reset() { this.counter = 0 }, }, })

Use a store in a component

defineStore returns a function. Call it inside a component's setup to get the store. To keep reactivity when you pull out individual values, use storeToRefs. Destructuring the store directly would lose reactivity for state and getters.

You can also return the whole store to the template to access it there.

  • Import the store from its file, for example @/stores/main
  • Use storeToRefs(main) to extract state or getters as refs
  • Return the whole store to the template if you need all of it
import { useMainStore } from '@/stores/main' import { storeToRefs } from 'pinia' export default defineComponent({ setup() { const main = useMainStore() const { counter, doubleCounter } = storeToRefs(main) return { main, counter, doubleCounter } }, })

Learn more and get help

The README links to the full documentation at pinia.vuejs.org, which covers SSR, Nuxt configuration, and composing stores. The FAQ notes that dynamic modules are not type safe, so the project suggests creating different stores that can be imported anywhere.

The project also offers live demos on StackBlitz for Vue 3 and Nuxt 3.

What people use it for

  • Keeping a logged-in user's details available to the header, profile page and settings page
  • Holding a shopping cart that several components read and update
  • Sharing filter or search settings between a list view and a sidebar
  • Storing data for a Nuxt app through the @pinia/nuxt module

Frequently asked questions

Is Pinia free to use?

Yes. The repository is licensed under the MIT License, which is an open-source licence. Check the LICENSE terms in the repository for the full conditions.

How do I install Pinia?

Run npm install pinia @vue/devtools-api in your project. The README also shows pnpm and yarn as alternatives. Then register it with createPinia() and app.use().

Does Pinia work with Vue 2?

The main version works with Vue 3. The README points to a separate v2 branch for Vue 2 support.

Is Pinia the successor to Vuex?

The Pinia FAQ answers yes and links to the Vue state management guide. Pinia is the library that Vue's documentation describes as succeeding Vuex.

Do I need Pinia for a small app?

Probably not. If you have only a few components and no shared state, a plain reactive object may be enough. Pinia is most useful when several components need the same data.

Why does my store lose reactivity when I destructure it?

Destructuring the store directly can break reactivity. Use storeToRefs(store) to extract state and getters while keeping them reactive, as shown in the component example.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

Pinia suits Vue 3 developers, especially those using TypeScript, the Composition API or Nuxt, who need state shared across many components. If you are on Vue 2 or your app has only a few components with no shared state, use the v2 branch or a plain reactive object instead, and compare alternatives such as Vuex, Zustand, Redux Toolkit or Jotai.

Install options & downloads