Capítulo 13: Gerenciamento de Estado Global Oficial com Pinia (defineStore)
Capítulo 13: Gerenciamento de Estado Global Oficial com Pinia (defineStore)
Especialização em Front-End com Vue • Vue 3 & Nuxt 3 • Composition API, Pinia, Vue Router, SSR e TypeScript
🗺️ Mapa Conceitual da Arquitetura Pinia
flowchart TD
A["Aplicação Vue 3 (createPinia())"] --> B["Store Pinia: defineStore('id', () => { ... })"]
subgraph SETUP_STORE["Setup Store (Estilo Composition API)"]
C["State: ref() e reactive()"]
D["Getters: computed()"]
E["Actions: Funções síncronas ou assíncronas"]
end
B --- SETUP_STORE
C & D -->|"storeToRefs(store): Desestruturação Segura"| F["Componente Consumidor A"]
E -->|"Desestruturação Direta de Ações"| F
B -->|"Reatividade Compartilhada"| G["Componente Consumidor B"]
subgraph RECURSOS["Vantagens sobre o Vuex"]
H["Zero Mutations (Atribuição Direta)"]
I["Suporte Nativo Total ao TypeScript"]
J["DevTools com Time-Travel Debugging"]
K["Modular por Padrão (Sem Namespaces complexos)"]
end
SETUP_STORE --- RECURSOS
style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
style B fill:#fff3e0,stroke:#ff9800,stroke-width:2px
style SETUP_STORE fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
style F fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
🏛️ 1. O Estado Global Oficial: Pinia
O Pinia é a biblioteca oficial de gerenciamento de estado do Vue 3, substituindo o antigo Vuex. Ele foi arquitetado para tirar pleno proveito do sistema de reatividade baseado em Proxy, oferecendo uma API extremamente concisa, tipagem TypeScript completa sem anotações complexas e suporte completo a SSR (Nuxt 3).
1.1 Fim das Mutações: Mutações Diretas e Claras
No Vuex, qualquer alteração de estado exigia a criação de uma Mutation síncrona com commits textuais (commit('SET_USER', payload)), o que gerava grande volume de código repetitivo e suscetível a erros de digitação.
No Pinia:
- Não existem mutations: O estado pode ser modificado diretamente no corpo de uma action ou até mesmo dentro de um componente (
store.count++). - DevTools Integradas: Toda alteração direta continua sendo rastreada com precisão milimétrica nas Vue DevTools, incluindo suporte a Time-Travel Debugging.
1.2 Option Stores vs Setup Stores
O Pinia suporta duas sintaxes de criação:
- Option Stores: Similar à Options API do Vue 2 (
state: () => ({ ... }),getters: { ... },actions: { ... }). - Setup Stores (Padrão Ouro): Utiliza exatamente a mesma sintaxe da Composition API:
ref()define o State.computed()define os Getters.- Funções regulares definem as Actions.
1.3 Desestruturação Segura com storeToRefs()
Um dos erros mais comuns de iniciantes é desestruturar propriedades de uma store diretamente (const { user, token } = useAuthStore()). Isso quebra a ligação reativa do Proxy!
- A Regra: Sempre utilize
storeToRefs(store)para desestruturar propriedades de estado (state) e cálculos derivados (getters). - Ações: As funções (
actions) são imutáveis e podem ser desestruturadas diretamente sem o auxílio dostoreToRefs.
⚖️ 2. Tabela Comparativa: Vuex 4 vs Pinia
| Critério de Comparação | Vuex 4 (Legado) | Pinia (Moderno / Oficial) |
|---|---|---|
| Arquitetura de Mutações | Exige mutations síncronas obrigatórias. |
Zero mutations; mutações diretas em actions. |
| Integração com TypeScript | Complexa; exige módulos tipados manualmente. | Inferência automática 100% de tipos e retornos. |
| Estrutura de Módulos | Árvore única aninhada com namespaced: true. |
Stores independentes e modulares por arquivo. |
| Tamanho do Pacote (Bundle) | ~10 KB. | ~1.5 KB (extremamente leve e tree-shakeable). |
| Suporte à Composition API | Parcial via adapters. | Nativo de primeira classe com Setup Stores. |
⚠️ 3. Armadilhas Comuns em Produção (Gotchas & Anti-Patterns)
Anti-Pattern 1: Desestruturar State sem storeToRefs
Erro Comum:
// ❌ QUEBRA DE REATIVIDADE
const authStore = useAuthStore();
const { currentUser } = authStore; // currentUser agora é estático! O template não atualizará.
Abordagem Correta: const { currentUser } = storeToRefs(authStore);.
Anti-Pattern 2: Chamar a Store fora do Ciclo de Instalação do App
Erro Comum: Executar const store = useAuthStore(); no nível raiz de um arquivo .ts antes de app.use(pinia).
Abordagem Correta: Invoque a função use...Store() dentro de funções executadas após o bootstrap da aplicação (dentro de componentes, guards de rota ou funções de serviço).
💻 4. Código Conceitual Arquitetural Comentado
// src/stores/userSessionStore.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export interface UserProfile {
id: string;
name: string;
role: 'ADMIN' | 'DEV' | 'AUDITOR';
}
export const useUserSessionStore = defineStore('userSession', () => {
// 1. STATE (Refs Reativos)
const currentUser = ref<UserProfile | null>(null);
const authToken = ref<string | null>(null);
// 2. GETTERS (Computed Properties)
const isAuthenticated = computed<boolean>(() => authToken.value !== null);
const isAdmin = computed<boolean>(() => currentUser.value?.role === 'ADMIN');
// 3. ACTIONS (Funções com mutação de estado e chamadas de I/O)
function setSession(user: UserProfile, token: string): void {
currentUser.value = user;
authToken.value = token;
}
function clearSession(): void {
currentUser.value = null;
authToken.value = null;
}
return {
currentUser,
authToken,
isAuthenticated,
isAdmin,
setSession,
clearSession
};
});
🛠️ 5. Cheat-Sheet do Pinia
// 1. Instalação e Bootstrap
import { createPinia } from 'pinia';
app.use(createPinia());
// 2. Consumo em Componente SFC
import { storeToRefs } from 'pinia';
import { useUserSessionStore } from '@/stores/userSessionStore';
const sessionStore = useUserSessionStore();
// Desestruturação de dados com storeToRefs:
const { currentUser, isAuthenticated } = storeToRefs(sessionStore);
// Desestruturação direta de ações:
const { setSession, clearSession } = sessionStore;