Use pinia state manager on vue 2 app without composition-api

Pinia is a state manager for vue2/3 apps. On this post, we’re going to use it on a existing Vue2 app without composition-api yet (it’s highly recommend to migrate your app to use composition-api/setup). We’re going to create a very simple store to be used on a existing component

Installing

On your app folder, install the pinia lib. You may also install ‘@vue/composition-api’ event if it’s not used (yet!)

npm install --save @vue/composition-ap
npm install --save pinia

On your vue setup file (usually main.js file), integrate the pinia with your vue app

import { createPinia, PiniaVuePlugin } from 'pinia'

Vue.use(PiniaVuePlugin)
const pinia = createPinia()

new Vue({
  el: '#app',
  // other options...
  // ...
  // note the same `pinia` instance can be used across multiple Vue apps on
  // the same page
  pinia,
})

Creating the store

For this example, we’re going to create a single store to be used in the application, but you can have as much as stores as you want in piratical cases. It will be a simple “count” store, with a simple “count” property with getters to retrieve that property and some actions to manipulate that property. You can add more properties, getters and actions to the store. To keep the minimal in this example, we’re having just the “count” to the “count.js” file.

export default defineStore('counter', {
  state: () => ({ 
    count: 0
  }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

Use the store on a component

Now we can use our store in any of our existing components by just importing it and adding its mappings to the “computed” property. The store can be accessed as ‘countStore’. Every update on the store will be reflected on all the components using it.

<template>
  <div>
    <p>{{ countStore.count }}</p>
    <p>Double: {{ countStore.doubleCount }}</p>
    <button @click="countStore.increment">Increment</button>
  </div>
</template>

<script>

import { mapStores } from 'pinia'
import useCountStore from 'stores/count.js'

export default {
  computed: {
    myExistingComputedProp: ()=>{return 'existingComputed'},
    // Each store will be accessible as its id + 'Store'
    // In this case, it will be acessed as "countStore"
    ...mapStores(useCountStore)
  }
}

</script>

Every update on the store will be reflected on all the components using it.

Written on April 17, 2023