State Management in Vue 3

matt
Matthew Gros · Nov 10, 2025

TLDR

Create stores for shared state, use composition API style, keep stores focused, don't over-use global state.

State Management in Vue 3

Pinia Replaced Vuex

Simpler API, better TypeScript support, and it just works.

Creating a Store

// stores/user.js
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
    state: () => ({
        user: null,
        loading: false,
    }),

    getters: {
        isLoggedIn: (state) => !!state.user,
        fullName: (state) => `${state.user?.firstName} ${state.user?.lastName}`,
    },

    actions: {
        async fetchUser() {
            this.loading = true
            this.user = await api.getUser()
            this.loading = false
        },

        logout() {
            this.user = null
        },
    },
})

Using the Store

<script setup>
import { useUserStore } from '@/stores/user'

const userStore = useUserStore()

// Access state
userStore.user
userStore.isLoggedIn

// Call actions
await userStore.fetchUser()
userStore.logout()
</script>

<template>
    <div v-if="userStore.isLoggedIn">
        Welcome, {{ userStore.fullName }}
    </div>
</template>

Composition API Style

export const useCartStore = defineStore('cart', () => {
    const items = ref([])

    const total = computed(() =>
        items.value.reduce((sum, item) => sum + item.price, 0)
    )

    function addItem(item) {
        items.value.push(item)
    }

    return { items, total, addItem }
})

When to Use Stores

Use stores for:

  • User authentication state
  • Shopping cart
  • App-wide settings
  • Data shared between routes

Don't use for:

  • Form state (keep local)
  • UI state (modals, dropdowns)
  • Data only one component needs

Persisting State

import { defineStore } from 'pinia'
import { useLocalStorage } from '@vueuse/core'

export const useSettingsStore = defineStore('settings', () => {
    const theme = useLocalStorage('theme', 'light')
    return { theme }
})

About the Author

matt

I build and ship automation-driven products using Laravel and modern frontend stacks (Vue/React), with a focus on scalability, measurable outcomes, and tight user experience. I’m based in Toronto, have 13+ years in PHP, and I also hold a pilot’s license. I enjoy working on new tech projects and generally exploring new technology.