Skip to content

Pinia na Prática

Ao usar o Pinia para gerenciar o estado em aplicações Vue.js com TypeScript, é importante seguir as melhores práticas para garantir a clareza do código, a reusabilidade e a manutenção fácil. Aqui estão alguns exemplos detalhados que demonstram como estruturar sua store Pinia de acordo com essas práticas:

1. Estruturação Básica da Store

Vamos começar com uma estrutura básica de store, usando TypeScript para definir explicitamente os tipos:

typescript
// src/stores/userStore.ts
import { defineStore } from "pinia";

interface UserState {
  name: string;
  email: string;
  loggedIn: boolean;
}

export const useUserStore = defineStore("user", {
  state: (): UserState => ({
    name: "",
    email: "",
    loggedIn: false,
  }),
  getters: {
    isAuthenticated(state: UserState): boolean {
      return state.loggedIn;
    },
  },
  actions: {
    logIn(email: string, name: string) {
      this.email = email;
      this.name = name;
      this.loggedIn = true;
    },
    logOut() {
      this.$reset();
    },
  },
});

Explicação:

  • State: Define as propriedades do estado com tipos específicos.
  • Getters: Funções computadas baseadas no estado que também podem ser tipadas para garantir que retornem o tipo correto.
  • Actions: Métodos para mudar o estado. Utilizamos $reset para redefinir o estado para seus valores iniciais, uma funcionalidade integrada do Pinia que ajuda a manter o estado consistente após o logout.

2. Uso de Store em Componentes

Com a store definida, aqui está como você pode usá-la em um componente Vue usando a Composition API:

vue
<script setup lang="ts">
import { useUserStore } from "@/stores/userStore";

const { name, logIn, logOut } = useUserStore();
</script>

<template>
  <div>
    <p v-if="isAuthenticated">Olá, {{ name }}!</p>
    <button @click="logIn('user@example.com', 'User')">Log In</button>
    <button @click="logOut" v-if="isAuthenticated">Log Out</button>
  </div>
</template>

Explicação:

  • O componente acessa a store usando a função useUserStore().
  • Os métodos e estados da store são expostos diretamente no template do componente, permitindo seu uso como se fossem parte do componente.

3. Modularização e Reusabilidade

Para projetos maiores, pode ser útil dividir a store em módulos. O Pinia suporta a modularização naturalmente, permitindo que você mantenha partes do estado e lógica relacionados juntos, mas separados de outras partes da aplicação.

typescript
// src/stores/cartStore.ts
import { defineStore } from "pinia";

interface CartItem {
  productId: string;
  quantity: number;
}

interface CartState {
  items: CartItem[];
}

export const useCartStore = defineStore("cart", {
  state: (): CartState => ({
    items: [],
  }),
  getters: {
    totalQuantity(state: CartState): number {
      return state.items.reduce((total, item) => total + item.quantity, 0);
    },
  },
  actions: {
    addToCart(productId: string, quantity: number) {
      const existingItem = this.items.find(
        (item) => item.productId === productId
      );
      if (existingItem) {
        existingItem.quantity += quantity;
      } else {
        this.items.push({ productId, quantity });
      }
    },
    removeFromCart(productId: string) {
      this.items = this.items.filter((item) => item.productId !== productId);
    },
  },
});

Melhores Práticas:

  • Isolamento de Estado: Mantenha o estado relacionado junto e isolado de outras partes da aplicação.
  • Tipagem Forte: Use TypeScript para definir interfaces claras para seu estado e ações.
  • Reusabilidade: Modularize o estado para reutilizá-lo em várias partes da aplicação sem redundância.

Seguir essas práticas ao usar o Pinia não só melhora a qualidade do código, mas também facilita a manutenção e escalabilidade da sua aplicação Vue.js.