Frontend Development 8 min read

Getting Started with Pinia: Installation, Store Creation, and Core Concepts

This guide introduces Pinia, a lightweight Vue state‑management library, covering its installation, creation of a Pinia instance, defining stores in both options and setup styles, and detailed usage of state, getters, and actions with code examples, highlighting its simplicity compared to Vuex.

政采云技术
政采云技术
政采云技术
Getting Started with Pinia: Installation, Store Creation, and Core Concepts

Introduction

As a front‑end developer you know that state management is a crucial part of daily development. This article introduces Pinia, the new rising star in the Vue ecosystem.

What is Pinia

Pinia, like Vuex, is a state‑management library designed specifically for Vue. It lets you share state across components or pages, offers a simpler API than Vuex, and supports both Vue 2.x and Vue 3.x.

Installation

yarn add pinia
// or using npm
npm install pinia

Creating a Pinia Instance

Create a Pinia instance (the root store) and pass it to the Vue application:

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')

How to Create a Store

A Store (such as one created with Pinia) is an entity that holds state and business logic. It contains three concepts: State , Getter , and Action , analogous to a component’s Data , Computed , and Methods .

Create a store file src/stores/counter.ts :

// stores/counter.ts

// Options mode
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
  state: () => {
    return { count: 0 }
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

// Setup mode
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function increment() {
    count.value++
  }
  return { count, increment }
})

The first argument of defineStore is a unique ID that links the store to the devtools. The second argument can be either a setup function or an options object.

State

Using state in a component:

import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
<script>
// inside template
<div class="greetings">{{counter.count}}</div>
</script>

Modify state directly or with $patch :

// Direct mutation
counter.count++

// Patch (can modify multiple properties)
counter.$patch({
  count: counter.count + 1,
})

Reset state to its initial value:

counter.$reset()

Destructure state (note: loses reactivity unless using storeToRefs ):

import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
const { count } = counter

Preserve reactivity with storeToRefs :

import { storeToRefs } from 'pinia'
const counter = useCounterStore()
const { count } = storeToRefs(counter)

Getter

Getters are equivalent to computed properties of the store. They can access the whole store via this , other stores, and can return functions that accept parameters (these are not cached).

import { useOtherStore } from './other-store'

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    // Simple computed getter
    doubleCount(state) {
      return state.count * 2
    },
    // Getter with explicit return type
    doublePlusOne(): number {
      return this.doubleCount + 1
    },
    // Access another store's getter
    otherGetter(state) {
      const otherStore = useOtherStore()
      return state.count + otherStore.count
    },
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

Action

Actions are similar to component methods; they can be asynchronous and can call other stores’ actions.

import { useAuthStore } from './user'

export const useCounterStore = defineStore('counter', {
  state: () => ({ userInfo: {} }),
  actions: {
    async fetchUserInfo() {
      const auth = useAuthStore()
      if (auth.isAuthenticated) {
        this.userInfo = await fetchUserInfo()
      }
    },
  },
})

Calling an action from a component:

<script setup>
const store = useCounterStore()
// Call the action as a method of the store
store.fetchUserInfo()
</script>

<template>
  <button @click="store.fetchUserInfo()">Click Me</button>
</template>

Conclusion

The above demonstrates the basic usage of Pinia. Compared with Vuex, Pinia’s API is much more concise: it drops mutations and modules, keeping only State, Getter, and Action, and its usage mirrors component Data , Computed , and Methods . It supports TypeScript and is extremely lightweight, with a bundle size of about 1 KB.

Reference

https://pinia.web3doc.top/

typescriptJavaScriptstate managementVuePiniastore
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.