[Pinia State Management] Comparison between Pinia and Vuex; creating Pinia Store; Pinia core concepts State, Getters, Actions

Directory

  • 1_Comparison between Pinia and Vuex
    • 1.1_Introduction to pinia
    • 1.2_The difference between Pinia and Vuex
  • 2_Create Pinia’s Store
    • 2.1_Installation and use
    • 2.2_Store
    • 2.3_Define a Store
  • 3_Pinia core concept State
    • 3.1_Understand and define State
    • 3.2_Operation State
  • 4_Pinia Core Concept Getters
    • 4.1_Understanding
    • 2.2_Access Getters
  • 5_Pinia Core Concept Actions
    • 5.1_Understanding
    • 5.2_Actions performs asynchronous operations

1_Comparison between Pinia and Vuex

1.1_Introduction to pinia

Pinia (pronounced /pi?nj?/, as in English “peenya”) is the word closest to pi?a (pineapple in Spanish);

  • Pinia started around 2019, initially as an experiment to redesign state management for Vue so that it can be used like a Composition API.
  • From then to now, the original design principles are still the same, and it is currently compatible with both Vue2 and Vue3, and does not require the use of Composition API;
  • Pinia is essentially still a state management library, used for state sharing across components and pages (this is the same as Vuex and Redux);

Visit official website

1.2_The difference between Pinia and Vuex

Why use Pinia when you have Vuex?

  • Pinia started out as an exploration of what the next iteration of Vuex would look like, incorporating many ideas from Vuex 5 core team discussions;
  • Eventually, the team realized that Pinia had already implemented most of the content in Vuex5, so it finally decided to use Pinia to replace Vuex;
  • Compared to Vuex, Pinia provides a simpler API with fewer rituals, providing a Composition-API style API;
  • Best of all, there’s solid type inference support when used with TypeScript;

Compared with Vuex, Pinia has many advantages:

  • For example, mutations disappear, reducing lengthy steps.
  • More friendly TypeScript support, Vuex’s previous support for TS was very unfriendly;
  • There is no longer a nested structure of modules, and each store can be used flexibly. They use each other in a flat manner;
  • There is no longer the concept of namespaces, and there is no need to remember their complex relationships;

2_Create Pinia’s Store

2.1_Installation and use

Execute the installation command, choose one of the two

yarn add pinia

npm install pinia

Create the index.js file under the src/store/ path or src/pinia/ path, write the code below, and then successfully create a pinia and can export it for use.

import {<!-- --> createPinia } from 'pinia'

const pinia = createPinia()

export default pinia

2.2_Store

What is a Store?

  • A Store (such as Pinia) is an entity that holds the state and business logic bound to the component tree, that is, it saves the global state;
  • More like a component that is always there and can be read and written by everyone;
  • Any number of Stores can be defined in the application to manage the state;

Store has three core concepts:

  • state, getters, actions;
  • Equivalent to the data, computed and methods of the component;
  • Once the store is instantiated, any properties defined in state, getters, and actions can be accessed directly on the store;

2.3_Define a Store

The Store is not created until it is used. You can use the Store by calling the use function.

For example, below, counter.js is a state management file that has been defined

<template>
  <div class="home">
    <h2>Home View</h2>
    <h2>count: {<!-- -->{<!-- --> counterStore.count }}</h2>
    <h2>count: {<!-- -->{<!-- --> count }}</h2>
    <button @click="incrementCount">count + 1</button>
  </div>
</template>

<script setup>
  import {<!-- --> storeToRefs } from 'pinia'
  import useCounter from '@/stores/counter';

  const counterStore = useCounter()

  const {<!-- --> count } = storeToRefs(counterStore)

  function incrementCount() {<!-- -->
    counterStore.count++
  }

</script>

Note that the Store cannot be deconstructed after being obtained, otherwise it will lose its responsiveness. In order to extract attributes from the Store while maintaining its responsiveness, you need to use storeToRefs()

3_Pinia core concept State

3.1_Understand and define State

State is the core part of the store because the store is used to help manage state. In Pinia, states are defined as functions that return an initial state;

For example, the code below/src/store/user.js

import {<!-- --> defineStore } from 'pinia'

const useUser = defineStore("user", {<!-- -->
  state: () => ({<!-- -->
    name: "coder",
    age: 18,
    level: 100
  })
})

export default useUser

3.2_Operation State

Reading and writing state, by default, the state can be read and written directly by accessing the state through the store instance;

import useUser from '@/stores/user';
const userStore = useUser()

userStore.age++
userStore.name = "xixi"

Reset State, you can reset the state to its initial value by calling the $reset() method on the store;

const userStore = useUser()
userStore.$reset()

Change State

  • In addition to directly using store.age + + to modify the store, you can also call the $patch method;
  • It allows multiple changes to be applied simultaneously using partial “state” objects;
const userStore = useUser()

userStore.$patch({<!-- -->
  name: "hhh",
  age: 25,
  Level: 50
})

Replacing State, you can replace the entire state of a Store by setting its $state property to a new object:

userStore.$state({<!-- -->
  name: "hehe",
  age: 10,
  level: 2
})

4_Pinia core concept Getters

4.1_Understanding

Getters are equivalent to the computed properties of Store:

  • They can be defined using the getters attribute in defineStore();
  • Getters can define functions that accept a state as a parameter;

For example src/store/counter.js

// Define the store about counter
import {<!-- --> defineStore } from 'pinia'

import useUser from './user'

const useCounter = defineStore("counter", {<!-- -->
  state: () => ({<!-- -->
    count: 99,
    friends: [
      {<!-- --> id: 111, name: "xixi" },
      {<!-- --> id: 112, name: "kobe" },
      {<!-- --> id: 113, name: "james" },
    ]
  }),
  getters: {<!-- -->
    //Basic usage
    doubleCount(state) {<!-- -->
      return state.count * 2
    }
})
export default useCounter

2.2_Visit Getters

Access the Getters of the current store

const conterStore = useCouter()
console.log(counterStore.doubleCount)
console.log(counterStore.doubleCountAddOne)

To access other Getters of your own in Getters, you can access all other properties of the current store instance through this;

 getters: {<!-- -->
   // 1. Basic usage
    doubleCount(state) {<!-- -->
      return state.count * 2
    },
    // 2. One getter introduces another getter
    doubleCountAddOne() {<!-- -->
      // this is a store instance
      return this.doubleCount + 1
    },
  }

Access Getters from other stores

 getters: {<!-- -->
  // Getters use data from other stores
    showMessage(state) {<!-- -->
      // 1. Get user information
      const userStore = useUser()

      // 2. Get your own information

      // 3. Splicing information
      return `name:${<!-- -->userStore.name}-count:${<!-- -->state.count}`
    }
  }

Getters can also return a function, which can accept parameters

 getters: {<!-- -->
    // getters also support returning a function
    getFriendById(state) {<!-- -->
      return function(id) {<!-- -->
        for (let i = 0; i < state.friends.length; i + + ) {<!-- -->
          const friend = state.friends[i]
          if (friend.id === id) {<!-- -->
            return friend
          }
        }
      }
    }
  }

5_Pinia core concept Actions

5.1_Understanding

Actions are equivalent to methods in components, which can be defined using the actions attribute in defineStore(), and they are very suitable for defining business logic;

Like getters, all operations of the entire store instance can be accessed through this in the action;

 actions: {<!-- -->
    increment() {<!-- -->
      this.count++
    },
    incrementNum(num) {<!-- -->
      this.count + = num
    }
  }

5.2_Actions performs asynchronous operations

Actions supports asynchronous operations, and you can write asynchronous functions and use await in the functions;

In action, you can access all operations of the entire store instance through `this`;

 actions: {<!-- -->
    increment() {<!-- -->
      this.count++
    },
    incrementNum(num) {<!-- -->
      this.count + = num
    }
  }