Skip to main content
The Pokedex application uses Pinia for state management, providing a simple and type-safe way to manage global state across components.

Pinia Setup

Pinia is initialized in the application entry point:
src/main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(createPinia()) 
app.use(router)

app.mount('#app')

Favoritos Store

The favoritos store manages the user’s favorite Pokemon list:
src/stores/favoritos.js
import { defineStore } from "pinia"
import { ref } from "vue"

export const useFavoritosStore = defineStore('favoritos', () => {
  const favoritos = ref([]);
  
  const anyadir = (poke) => {
    favoritos.value.push(poke.name);
  }
  
  const eliminar = (poke) => {
    favoritos.value.splice(favoritos.value.indexOf(poke), 1);
  }
  
  return {
    favoritos,
    anyadir,
    eliminar
  }
})

Store Structure

favoritos

Type: ref<Array>Description: Array of favorite Pokemon namesInitial Value: []
const favoritos = ref([]);

anyadir(poke)

Description: Adds a Pokemon to favoritesParameters:
  • poke - Pokemon object with a name property
Usage:
anyadir({ name: 'pikachu' })

eliminar(poke)

Description: Removes a Pokemon from favoritesParameters:
  • poke - Pokemon name (string)
Usage:
eliminar('pikachu')

Using the Store in Components

The store is used in components through the Composition API:

Basic Usage

src/views/PokeView.vue
<script setup>
import { useFavoritosStore } from '@/stores/favoritos'
import { storeToRefs } from 'pinia'
import { computed } from 'vue'

// Get the store instance
const useFavorito = useFavoritosStore()

// Destructure actions (these remain reactive)
const { anyadir } = useFavorito

// Destructure state with storeToRefs to maintain reactivity
const { favoritos } = storeToRefs(useFavorito)
</script>

Important: storeToRefs

Always use storeToRefs() when destructuring state properties to preserve reactivity. Direct destructuring will lose reactivity!
// ✅ Correct - maintains reactivity
const { favoritos } = storeToRefs(useFavorito)

// ❌ Wrong - loses reactivity
const { favoritos } = useFavorito

Adding to Favorites

src/views/PokeView.vue
<script setup>
import { useFavoritosStore } from '@/stores/favoritos'
import { useGetData } from '@/composables/useGetData'

const useFavorito = useFavoritosStore()
const { anyadir } = useFavorito
const { datos } = useGetData()

const addToFavorites = () => {
  anyadir(datos.value)
  // Show notification or feedback
}
</script>

<template>
  <button @click="addToFavorites" class="favorite-button">
    ☆ Añadir a favoritos
  </button>
</template>

Checking if Pokemon is Favorite

src/views/PokeView.vue
<script setup>
import { useFavoritosStore } from '@/stores/favoritos'
import { storeToRefs } from 'pinia'
import { computed } from 'vue'

const useFavorito = useFavoritosStore()
const { favoritos } = storeToRefs(useFavorito)

const isFavorite = computed(() => {
  return favoritos.value.some(pokemon => pokemon.name === datos.value?.name)
})
</script>

<template>
  <button 
    @click="addToFavorites" 
    class="favorite-button"
    :class="{ 'is-favorite': isFavorite }"
  >
    {{ isFavorite ? '★ En favoritos' : '☆ Añadir a favoritos' }}
  </button>
</template>

Removing from Favorites

<script setup>
import { useFavoritosStore } from '@/stores/favoritos'
import { storeToRefs } from 'pinia'

const useFavorito = useFavoritosStore()
const { eliminar } = useFavorito
const { favoritos } = storeToRefs(useFavorito)

const removeFromFavorites = (pokemonName) => {
  eliminar(pokemonName)
}
</script>

<template>
  <div v-for="poke in favoritos" :key="poke">
    <span>{{ poke }}</span>
    <button @click="removeFromFavorites(poke)">
      Remove
    </button>
  </div>
</template>

Setup Syntax vs Options API

This store uses Pinia’s Setup Syntax (recommended for Vue 3):
export const useFavoritosStore = defineStore('favoritos', () => {
  const favoritos = ref([])
  
  const anyadir = (poke) => {
    favoritos.value.push(poke.name)
  }
  
  return { favoritos, anyadir }
})

State Persistence

Current Limitation

The current implementation does not persist favorites across page refreshes. Favorites are stored only in memory.To add persistence, consider using:
  • localStorage via Pinia plugins
  • sessionStorage for session-only persistence
  • Backend API for cross-device synchronization

Example: Adding Persistence

import { defineStore } from "pinia"
import { ref, watch } from "vue"

export const useFavoritosStore = defineStore('favoritos', () => {
  // Load from localStorage on initialization
  const stored = localStorage.getItem('favoritos')
  const favoritos = ref(stored ? JSON.parse(stored) : [])
  
  // Save to localStorage on changes
  watch(favoritos, (newFavoritos) => {
    localStorage.setItem('favoritos', JSON.stringify(newFavoritos))
  }, { deep: true })
  
  const anyadir = (poke) => {
    favoritos.value.push(poke.name)
  }
  
  const eliminar = (poke) => {
    favoritos.value.splice(favoritos.value.indexOf(poke), 1)
  }
  
  return { favoritos, anyadir, eliminar }
})

Best Practices

Always destructure state with storeToRefs() to maintain reactivity:
const { favoritos } = storeToRefs(useFavoritosStore())
Actions can be destructured directly without losing reactivity:
const { anyadir, eliminar } = useFavoritosStore()
Store instances are automatically singletons. Multiple calls to useFavoritosStore() return the same instance:
const store1 = useFavoritosStore()
const store2 = useFavoritosStore()
// store1 === store2 (same instance)
Always validate data before mutating the store:
const anyadir = (poke) => {
  if (!poke?.name) return
  if (favoritos.value.includes(poke.name)) return
  favoritos.value.push(poke.name)
}

Store DevTools

Vue DevTools Integration

Pinia integrates with Vue DevTools for debugging:
  • View current state
  • Track state mutations
  • Time-travel debugging
  • Action history

Next Steps

Composables

Learn about reusable composition functions

Routing

Understand route configuration and navigation

Build docs developers (and LLMs) love