Skip to content

This repository serves as a knowledge hub for all things related to Pinia state management in Vue.js. Explore a wealth of information, including explanations, sample code, and strategies for efficient state handling using Pinia.

Notifications You must be signed in to change notification settings

rakibsarowar/Pinia-handnote

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 

Repository files navigation


Pinia Hand note


A hand note of Pinia journey.....


Key Note
Emoji Description Emoji Description
🌴 Main Topic 📌 Regular Note
🌿 Paragraph 💎 High Value info
📕 Heavy Note 🧨 Careful this
🍂 Attention Note Stop! check the point
🏷️ Regular Note 🎯 Focus
##Expand Table of Contents

🌴 Pattern for State management:

Vue Vs Pinia


  • Vue use data: {} for storing data, on the other hand pinia use state: {}

  • Vue use methods: {} for updating data of local state , on the other hand pinia use actions: {}

  • Vue use computed: {} for returning process version data without effecting original data, on the other hand pinia use state: {}


Pinia Process

🌴 What is a Store?


A Store (like Pinia) is an entity holding state and business logic that isn't bound to your Component tree. In other words, it hosts global state. It's a bit like a component that is always there and that everybody can read off and write to. It has three concepts, the state, getters and actions and it's safe to assume these concepts are the equivalent of data, computed and methods in components.

🌴 When should I use a Store


A store should contain data that can be accessed throughout your application. This includes data that is used in many places, e.g. User information that is displayed in the navbar, as well as data that needs to be preserved through pages, e.g. a very complicated multi-step form.

On the other hand, you should avoid including in the store local data that could be hosted in a component instead, e.g. the visibility of an element local to a page.

Not all applications need access to a global state, but if yours need one, Pinia will make your life easier.

🌴 Learning By Project

🌴 Installation:


🌿 Step 01: Install pinia

yarn add pinia

# or with npm

npm install pinia


🌿 Step 02: Create a pinia instance (the root store) and pass it to the app as a plugin

<!-- main.js  -->

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


🌴 Creating First Store:


🌿 Step 01: Now create components of TodoAPP.vue, TodoForm.vue, TodoList.vue.
🌿 Step 02: import TodoForm.vue, TodoList.vue. in TodoApp.Vue.
🌿 Step 03: and import TodoApp.vue in App.vue. and delete every thing of App.Vue rest.
🌿 Step 04 Store Create: create stores folder and create in the todoList.js

import { defineStore } from 'pinia'

export const useTodoListStore = defineStore('todoList', {
  
  // State
  // getters
  // actions
})


🌿 Step 05: now create Global state object state: () => ({ todoList: []})
And final code will be like below,

import { defineStore } from 'pinia'

export const useTodoListStore = defineStore('todoList', {
  state: () => ({
    todoList: [],
  })
})

🌴 Mutating state with action (Create):


🌿 Step 1: now create action: where we will add toDO item into the state,

actions: {
    addTodo(item) {
        this.todoList.push({item, id: this.id++})
    }
}

🌿 Step 02: also add id:0 property to the state: Since we want to has id in each item while increment in pushing into the array,

import { defineStore } from 'pinia'

export const useTodoListStore = defineStore('todoList', {
  state: () => ({
    todoList: [],
    id: 0
  })
})

🌿 Step 03: and each toDo will start out as incomplete completed: false


🌿 Step 04: we can also write to action for deleting item by filtering the id on the toDo object.

deleteTodo(itemId) {
      this.todoList = this.todoList.filter((object) => {
        return object.id !== itemId
      })
    }


Final all codes:

import { defineStore } from 'pinia'

export const useTodoListStore = defineStore('todoList', {
  state: () => ({
    todoList: [],
    id: 0
  }),
  actions: {
    addTodo(item) {
      this.todoList.push({ item, id: this.id++, completed: false })
    },
    deleteTodo(itemId) {
      this.todoList = this.todoList.filter((object) => {
        return object.id !== itemId
      })
    },
  }
})


🌿 5. Now create simple form:

<script setup>
import { ref } from 'vue'
import { useTodoListStore } from '@/stores/todoList'

const todo = ref('')
const store = useTodoListStore()

function addItemAndClear(item) {
  if (item.length === 0) {
    return
  }
  // invokes function in the store:
  store.addTodo(item)
  todo.value = ''
}
</script>

<template>
  <div>
    <form @submit.prevent="addItemAndClear(todo)">
      <input v-model="todo" type="text" /><button>Add</button>
    </form>
  </div>
</template>

<style scoped>
</style>

- ✋ in here we use ``` ref('') ``` to reactive the form. which will update the value of the user types in the input.
- now we have to access the store so we use:
import { useTodoListStore } from '@/stores/todoList'

const store = useTodoListStore()


  • then we validate the input, if ok we sent the item and clear the form:

function addItemAndClear(item) {
  if (item.length === 0) {
    return
  }
  // invokes function in the store:
  store.addTodo(item)
  todo.value = ''
} 
  • then we add the function in the form submit handler:
<form 
@submit.prevent="addItemAndClear(todo)"
> 
<from/>


🌴 Reactive Properties in Pinia (Write):


Now go to TodoList.Vue.

🌿 1. import store:

import { useTodoListStore } from '@/stores/todoList'
const store = useTodoListStore()


🌿 2. StoreToRefs
we will import that storeToRefs: its help to bring property from the store with ensuring reactivity each item.

// storeToRefs lets todoList keep reactivity:
const { todoList } = storeToRefs(store)


now render the code in
<script setup>
import { useTodoListStore } from '@/stores/todoList'
import { storeToRefs } from 'pinia'

const store = useTodoListStore();

// storeToRefs lets todoList keep reactivity:
const { todoList } = storeToRefs(store)

// destructuring action method doesn't require using storeToRefs:
const { toggleCompleted } = store

</script>

<template>
  <div v-for="todo in todoList" :key="todo.id" class="list">
    <div class="item">
      <span :class="{ completed: todo.completed }">{{ todo.item }}</span>
      <span @click.stop="toggleCompleted(todo.id)">&#10004;</span>
    </div>
  </div>
</template>

<style scoped>
.completed {
  text-decoration: line-through;
}
</style>


Now go to store.js and remember that we use ``` completed: false ``` in action. we want to check the id and find the item is completed or not completed.
    toggleCompleted(idToFind) {
      const todo = this.todoList.find((obj) => obj.id === idToFind);
      if (todo) {
        todo.completed = !todo.completed
      }
    }


Now again go to the TodoList.vue,
import the toggleCompleted action. add a event lister to listen the click of check mark which will invoke the toggle action in store.
<span @click.stop="toggleCompleted(todo.id)">&#10004;</span>

🌴 Deleting state from the store.


we already write the delete action in store,
deleteTodo(itemId) {
      this.todoList = this.todoList.filter((object) => {
        return object.id !== itemId
      })
    },
    

now import that in toDoList.vue, and add a event lister which also invoke the delete function:
<span @click="deleteTodo(todo.id)" class="x">&#10060;</span>

DONE!!!!!!

<!-- main.js -->

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)

app.use(createPinia())

app.mount('#app')


<!-- App.vue -->

<script setup>
import TodoApp from './components/TodoApp.vue'
</script>

<template>
  <todo-app />
</template>

<style>
* {
  margin: 0;
  padding: 0;
}
#app {
  background-color: #597d9a;
  display: flex;
  justify-content: center;
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>


<!-- TodoApp.vue -->

<script setup>
import TodoForm from './TodoForm.vue'
import TodoList from './TodoList.vue'
</script>

<template>
  <div class="todo-app">
    <h1>To Do List</h1>
    <todo-form />
    <todo-list />
  </div>
</template>

<style scoped>
.todo-app {
  padding: 5vh;
  min-height: 100vh;
  width: 30vw;
  background-color: #f7f9fc;
}
</style>


<!-- TodoForm.vue -->

<script setup>
import { ref } from 'vue'
import { useTodoListStore } from '@/stores/todoList'

const todo = ref('')

const store = useTodoListStore()

function addItemAndClear(item) {
  if (item.length === 0) {
    return
  }
  // invokes function in the store:
  store.addTodo(item)
  todo.value = ''
}

</script>

<template>
  <div>
    <form @submit.prevent="addItemAndClear(todo)">
      <input v-model="todo" type="text" /><button>Add</button>
    </form>
  </div>
</template>

<style scoped>
form {
  margin-bottom: 15px;
}
input {
  margin-top: 25px;
  margin-bottom: 15px;
  height: 20px;
  width: 50%;
}
button {
  margin-left: 30px;
  background-color: #2f6089;
  padding: 5px 10px;
  border: none;
  border-radius: 5px;
  font-weight: 800;
  color: white;
  width: 15%;
}
.alert-div {
  min-height: 25px;
}
.alert {
  color: #d1495b;
  font-size: 1em;
  font-weight: 600;
}
</style>


<!-- TodoList.vue -->

<script setup>
import { useTodoListStore } from '@/stores/todoList'
import { storeToRefs } from 'pinia'

const store = useTodoListStore()

// storeToRefs lets todoList keep reactivity:
const { todoList } = storeToRefs(store)

// destructuring action method doesn't require using storeToRefs:
const { toggleCompleted, deleteTodo } = store

</script>

<template>
  <div v-for="todo in todoList" :key="todo.id" class="item">
    <div class="content">
      <span :class="{ completed: todo.completed }">{{ todo.item }}</span>
      <div>
        <span @click.stop="toggleCompleted(todo.id)">&#10004;</span>
        <span @click="deleteTodo(todo.id)" class="x">&#10060;</span>
      </div>
    </div>
  </div>
</template>

<style scoped>
span {
  margin: 0 10px;
  cursor: pointer;
}
.item {
  display: flex;
  justify-content: center;
}
.content {
  display: flex;
  font-size: 1.5em;
  justify-content: space-between;
  width: 80vw;
  padding: 5px;
}
.completed {
  text-decoration: line-through;
}
</style>


<!-- Store/ todoList.js -->

import { defineStore } from 'pinia'

export const useTodoListStore = defineStore('todoList', {
  state: () => ({
    todoList: [],
    id: 0
  }),
  actions: {
    addTodo(item) {
      this.todoList.push({ item, id: this.id++, completed: false })
    },
    deleteTodo(itemId) {
      this.todoList = this.todoList.filter((object) => {
        return object.id !== itemId
      })
    },
    toggleCompleted(idToFind) {
      const todo = this.todoList.find((obj) => obj.id === idToFind)
      if (todo) {
        todo.completed = !todo.completed
      }
    }
  }
})

About

This repository serves as a knowledge hub for all things related to Pinia state management in Vue.js. Explore a wealth of information, including explanations, sample code, and strategies for efficient state handling using Pinia.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages