Pinia for State Management
Using Pinia for state management in Vue appsโ
๐ What is Pinia?โ
Pinia allows you to store data and methods (aka variables and functions) in a central way, and import them to different components throughout your app. This can simplify your code by importing and using variables and functions only in the components where they are needed. This avoids prop drilling and several layers of callback functions!
Here is the documentation. ๐
When to use it?โ
โ ย Use Pinia to store any data and methods that need to be accessible across multiple components. Ex:
myData
needs to be set inComponent.vue
, but displayed inSiblingComponent.vue
Component.vue
needs to fetch data based on some action in that component, butSiblingComponent.vue
needs to display, edit or remove the same data.myData
andotherData
are rendered in different components, but are both used in a third component to calculate some outcome.
โย Do not use Pinia for data that is only used temporarily, or in a single component. Ex:
Component.vue
temporarily sets aselectedItem
- some function is performed on the selected item, then it clears when a new item is selected.Component.vue
usesspecificData
that never needs to be passed to or used in other components.
How to use it?โ
Create a store ๐๏ธโ
First, create your store file and name it with this pattern: useExampleStore.js
- i.e.
use
+YourStoreName
+Store
- so for example, for RMT's disease status data:
useDiseaseStatusStore.js
Step-by-step instructions in comments below.
You can look at examples in the codebase in client > src > stores
.
// ******* STEP 1: import defineStore at the top *******
import { defineStore } from "pinia";
// ******* STEP 2: export your store, and after defineStore, give your store a unique descriptive name *******
export const useExampleStore = defineStore("example", {
// ******* STEP 3: define your data/variables in state *******
state: () => ({
myVariable: [],
anotherVariable: "I โค๏ธ Pinia",
}),
// ******* STEP 4: define your functions/methods in "actions" *******
actions: {
async myFunction(params) {
// your code...
},
anotherFunction() {
// your code...
},
},
});
// ******* THAT'S IT! Congrats :) *******
Use a store ๐งคโ
Hereโs a ๐ฌย how-to video
Process to use stored data or methods in any component is:
- In
<script>
, import:- the correct store
mapState
if youโre using data/variablesmapActions
if youโre using functions/methods
import { useExampleStore } from "@/stores/useExampleStore";
import { mapState, mapActions } from "pinia";
- For data/variables, add a
computed
property in your<script>
, and usemapState
to destructure your stored data:
computed: {
...mapState(useExampleStore, ['myVariable', 'anotherVariable'])
},
- For functions/methods, use
mapActions
in yourmethods
to destructure the stored functions. You do not need to include params, just function names:
methods: {
...mapActions(useExampleStore, ['myFunction', 'anotherFunction'])
},
- Then you can use as usual! i.e. Use the variables in your
<template>
, call the functions, etc., with the same syntax as if they were standarddata
ormethods
.
<div>
<select @change="myFunction(value)">
<option v-for="item in myVariable" :key="item.id" :value="item.name">
{{ item.name }}
</option>
</select>
</div>