Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Pinia — State Management

What is Pinia?

Pinia is the official state management library for Vue 3. It replaces Vuex with a simpler, more intuitive API. Pinia stores are like components without a template — they hold reactive state that any component can access.

  • State — reactive data (like data() in components)
  • Getters — computed values derived from state
  • Actions — methods that modify state (can be async)
Pinia — Store Definition and Usage
// stores/counter.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

// Setup store (Composition API style — recommended)
export const useCounterStore = defineStore('counter', () => {
    // State
    const count = ref(0)
    const history = ref([])

    // Getters (computed)
    const doubleCount = computed(() => count.value * 2)
    const isPositive  = computed(() => count.value > 0)

    // Actions
    function increment() {
        count.value++
        history.value.push(`+1 → ${count.value}`)
    }

    function decrement() {
        count.value--
        history.value.push(`-1 → ${count.value}`)
    }

    function reset() {
        count.value = 0
        history.value = []
    }

    function incrementBy(amount) {
        count.value += amount
    }

    return { count, history, doubleCount, isPositive, increment, decrement, reset, incrementBy }
})

// Options store (Options API style)
export const useCounterOptionsStore = defineStore('counterOptions', {
    state: () => ({ count: 0 }),
    getters: {
        double: (state) => state.count * 2
    },
    actions: {
        increment() { this.count++ },
        async fetchCount() {
            const res = await fetch('/api/count')
            this.count = await res.json()
        }
    }
})
// stores/auth.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useAuthStore = defineStore('auth', () => {
    const user = ref(null)
    const token = ref(localStorage.getItem('token'))
    const loading = ref(false)

    const isLoggedIn = computed(() => !!token.value)
    const userName   = computed(() => user.value?.name || 'Guest')

    async function login(email, password) {
        loading.value = true
        try {
            const res = await fetch('/api/login', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ email, password })
            })
            const data = await res.json()
            user.value  = data.user
            token.value = data.token
            localStorage.setItem('token', data.token)
        } finally {
            loading.value = false
        }
    }

    function logout() {
        user.value  = null
        token.value = null
        localStorage.removeItem('token')
    }

    return { user, token, loading, isLoggedIn, userName, login, logout }
})
<template>
  <div>
    <!-- Counter store -->
    <p>Count: {{ counter.count }}</p>
    <p>Double: {{ counter.doubleCount }}</p>
    <button @click="counter.increment()">+1</button>
    <button @click="counter.decrement()">-1</button>
    <button @click="counter.reset()">Reset</button>

    <!-- Auth store -->
    <p v-if="auth.isLoggedIn">Hello, {{ auth.userName }}!</p>
    <button v-if="!auth.isLoggedIn" @click="auth.login('alice@example.com', 'password')">
      Login
    </button>
    <button v-else @click="auth.logout()">Logout</button>
  </div>
</template>

<script setup>
import { useCounterStore } from '@/stores/counter'
import { useAuthStore } from '@/stores/auth'

// Use stores — reactive, auto-updates template
const counter = useCounterStore()
const auth    = useAuthStore()

// Destructure with storeToRefs (preserves reactivity)
import { storeToRefs } from 'pinia'
const { count, doubleCount } = storeToRefs(counter)
// Actions can be destructured directly (not reactive)
const { increment, reset } = counter
</script>

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.