SyntaxStudy
Sign Up
Vue.js Introduction to Pinia Stores
Vue.js Beginner 1 min read

Introduction to Pinia Stores

Pinia is the official state management library for Vue 3, replacing Vuex. It provides a simpler API with full TypeScript support, devtools integration, and plugin extensibility. A Pinia store is defined with `defineStore(id, options)` where the `id` is a unique string used for devtools and the options define state, getters, and actions. Unlike Vuex, Pinia has no mutations — state is mutated directly inside actions or via `$patch`. There are no nested modules; instead you create multiple flat stores and compose them by importing one store into another. This flat structure with explicit imports makes dependencies between stores easy to reason about and to test in isolation. Every store is reactive. When a component reads store state, it automatically tracks that dependency and re-renders when the state changes. Install Pinia in your app by creating an instance with `createPinia()` and registering it with `app.use(pinia)`.
Example
// src/stores/counter.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';

// Composition-API (setup) style store
export const useCounterStore = defineStore('counter', () => {
  // State
  const count = ref(0);
  const step  = ref(1);

  // Getter (computed)
  const doubled = computed(() => count.value * 2);

  // Actions
  function increment() { count.value += step.value; }
  function decrement() { count.value -= step.value; }
  function reset()     { count.value = 0; }

  return { count, step, doubled, increment, decrement, reset };
});

// ── Component usage ───────────────────────────
<script setup>
import { useCounterStore } from '@/stores/counter';

const counter = useCounterStore();
// Access state reactively
console.log(counter.count, counter.doubled);
</script>

<template>
  <p>Count: {{ counter.count }} (×2 = {{ counter.doubled }})</p>
  <button @click="counter.increment">+</button>
  <button @click="counter.decrement">−</button>
  <button @click="counter.reset">Reset</button>
</template>