100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
JavaScript

Pinia Basics

Get started with Pinia, Vue's official state management library, covering stores, state, and how components read and mutate shared data.

State ManagementIntermediate9 min readJul 9, 2026
Analogies

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.

javascript
// 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.

vue
<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

Was this page helpful?

Topics covered

#JavaScript#VueJsStudyNotes#WebDevelopment#PiniaBasics#Pinia#Defining#Store#Inside#StudyNotes#SkillVeris