Pinia is one of the newest projects from the Vue ecosystem and it is the new official state management tool for Vue.js apps. Its API is similar to Vuex (its predecessor) and it is designed to be faster and more lightweight. According toPinia's Official Website, Pinia was born out of the experiment to redesign what a Store for Vue could look like with the Composition API. It is an upgrade on Vuex and compatible with Vue 2 and options API.
Note: This tutorial uses<script setup>
, composition API and Vue 3.
Installation
Run the following code in your terminal to create a new Vue project.
Input the project name in the command prompt.
Select Vue.
Select yes when the command prompt asks to add Pinia to state management system.
npmcreatevite@latest
Pinia can be installed in an existing application with npm. Run the following command in your terminal to install Pinia in an existing application.
npminstallpinia//oryarnaddpinia
Project Configuration
The application has to know to use Pinia, so we tell it to use it in themain.js
file.
import{createApp}from'vue'import{createPinia}from'pinia'importAppfrom'./App.vue'import'./style.css'constpinia=createPinia()constapp=createApp(App)app.use(pinia)app.mount('#app')
We importedcreatePinia
fromPinia
, instantiated it and instructed the application to use it by simply adding it to the Vue application's instance.
Pinia Store Setup
Create astores
folder in thesrc
folder. In the newly createdstores
folder, create aproducts.js
file.
The store file isprojects.js
in our case here
Next, we need to importdefineStore
in theproducts.js
file and use it.
import{defineStore}from"pinia"constuseProductsStore=defineStore("products",{state:()=>({products:[description:"Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday",category:"men's clothing",image:"https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg",rating:{rate:3.9,count:120},]}),getters:{},actions:{},})
We use thedefineStore()
method by:
Assigning it to a variable. Even though you can name the variable anything, the convention is to start the nameuse, then the name of the store file in singular and end it withstore. In this case, the variable name is
useProducutStore
The
defineStore()
takes an optional name which is the name of the store and an options object. This serves as an id for the store.The options object houses the
state
,setters
andactions
objects and I have added aproducts
array that contains a single product.
Unlike in Vuex, Pinia does not have amutations
object, theactions
are where mutation of state and asynchronous request happens.
The options object is very similar to the options API. The setters are like the computed properties and actions, like methods.
I love this because not being able to put state mutation and methods that make API calls in one object has been a pain. It has led to having methods with similar names both in mutations and actions, the one in actions makes the API call while the one in mutations adds the fetched data into the state.
We are going to add a couple of states and methods to the options object.
import{defineStore}from"pinia"exportconstuseProductsStore=defineStore("products",{state:()=>({counter:0,categories:[],products:[{id:1,title:"Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops",price:109.95,description:"Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday",category:"men's clothing",image:"https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg",rating:{rate:3.9,count:120},},],}),getters:{getCounter:state=>state.counter,getAllProducts:state=>state.products.length,},actions:{incrementCounter(){this.counter++},addProduct(product){if(!product.length)returnthis.products.push(product)},asyncgetCategories(){awaitfetch("https://fakestoreapi.com/products/categories").then(res=>res.json()).then(data=>{this.categories.push(data)})},},})
In the code above, I have added:
categories
state to store the categories.counter
state to count arbitrary numbers.getCounter()
getter to get the currentcounter
's count.getAllProducts()
getter all products.incrementCounter()
action to increment the counter.addProduct()
action to add a product.getCategories()
action to make an asynchronous call to an endpoint that gets all categories and populate them to state.
In theactions
object, the state is not passed into the functions, rather, they are accessed throughthis
keyword.this
return the current store instance. This implies that allactions
functions must be regular functions and not arrow functions.
import{defineStore}from"pinia"exportconstuseProductsStore=defineStore("products",{...getters:{getCounter(){this.counter},getAllProducts(){this.products.length},},...})
In the getters objects, the state can be substituted withthis
keyword, which returns the store instance. Meaning, the arrow functions have to be changed to regular functions.
How to access Pinia getters in another getter
Getters can be accessed and used in another getter usingthis
keyword.
getters:{...getAllProducts(){returnthis.products.length},doubleProductsSize(){returnthis.getAllProducts*2},},
We doubled the size of all the products that were returned bygetAllProducts()
getter in the newdoubleProductsSize()
getter.
How to access Pinia actions in another getter
Actions can be accessed and used in another action usingthis
keyword.
actions:{incrementCounter(){this.counter=this.counter+1},...asyncgetCategories(){this.incrementCounter()awaitfetch("https://fakestoreapi.com/products/categories").then(res=>res.json()).then(data=>{this.categories.push(data)})},},
We incremented the counter each time we get all products categories by callingincrementCounter()
action in thegetCategories()
async action.
How to access Pinia state in Vue components
In the components, Pinia states are accessed by importing the store in the component and passing it into astoreToRefs()
method provided by Pinia where they can be destructured before they are used.storeToRefs()
helps to extract the state while keeping its reactivity.
import{useProductsStore}from"./stores/products"import{storeToRefs}from"pinia"conststore=useProductsStore()const{categories,counter,products}=storeToRefs(store)
How to access Pinia getters in Vue components
Getters can be accessed on the object instance.
import{useProductsStore}from"./stores/products"conststore=useProductsStore(){{store.getCounter}}{{store.getAllProducts}}
They can also be destructured by passing the store object instance through thestoreToRefs()
method.
import{useProductsStore}from"./stores/products"conststore=useProductsStore()const{getCounter,getAllProducts}=storeToRefs(store)
How to access Pinia actions in Vue components
Action methods can be destructured off the store object instance.
import{useProductsStore}from"./stores/products"conststore=useProductsStore()const{getCategories}=storeonBeforeMount(()=>getCategories())
They can be accessed on the store object instance directly.
import{useProductsStore}from"./stores/products"conststore=useProductsStore()onBeforeMount(()=>store.getCategories())
Conclusion
Pinia is a state management library for Vue.js that provides a way to manage and share reactive states across components in a Vue.js application.
In this tutorial, we learned how to create a Pinia store using thedefineStore()
function and use it in a Vue.js component. We saw how to define state properties, getters and actions functions that can mutate the state and perform asynchronous calls in the store, and how to access them in a component using theuseStore()
andstoreToRefs()
functions provided by Pinia.
Pinia provides a powerful and flexible way to manage states in Vue.js applications, and it's well-suited to large and complex applications where state management can become a challenge. Its use of the Composition API makes it easy to use and understand, and its integration with Vue.js 3 means that it works seamlessly with other Vue.js features and libraries.
Overall, Pinia is a great choice for developers looking for a modern and flexible state management library for their Vue.js applications. It provides a solid foundation for building complex and scalable applications, and its simple and intuitive API makes it easy to learn and use.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse