SpikeMe

Documento de exemplo

Um spike de verdade gerado pelo SpikeMe. É exatamente isto que você recebe.

Spike: Gerência de estado global (React 19 + Vite)

Projeto acme-dashboard (React 19.1, Vite 6, TypeScript 5.6, pnpm). Hoje o estado vive em prop drilling e alguns useContext; conforme o dashboard cresceu, re-renders e o acoplamento entre telas viraram atrito. Este spike compara três abordagens para um store global, com foco na stack real.

Objetivo e critérios de decisão

  • Bundle: peso gzip somado ao app (orçamento apertado no first load).
  • Curva e DX: quão rápido o time entrega sem boilerplate.
  • Modelo mental: store único vs. átomos; previsibilidade dos re-renders.
  • Maturidade: adoção, manutenção ativa, ecossistema de middleware.
  • Compatibilidade: React 19 + Vite + TS estrito, sem gambiarra.

Opções analisadas

Opção 1 — Zustand

Store como hook, fora da árvore React; seletores controlam o re-render.

import { create } from "zustand";
type Store = { count: number; inc: () => void };
export const useStore = create<Store>((set) => ({
  count: 0,
  inc: () => set((s) => ({ count: s.count + 1 })),
}));

Prós: API mínima, sem provider, seletores enxutos, ótimo TS. Contras: disciplina de seletores fica com o time; sem opinião de arquitetura.

Opção 2 — Jotai

Estado como átomos compostos; re-render só de quem lê o átomo.

import { atom, useAtom } from "jotai";
const countAtom = atom(0);
export const useCount = () => useAtom(countAtom);

Prós: granularidade natural, excelente para estado derivado. Contras: muitos átomos espalham a lógica; curva conceitual maior.

Opção 3 — Redux Toolkit

Store previsível com slices, devtools e middleware padronizados.

Prós: convenção forte, devtools e RTK Query maduros, escala em time grande. Contras: mais boilerplate e maior peso; excessivo para um dashboard médio.

Comparação

CritérioZustandJotaiRedux Toolkit
Bundle (gzip)~1,1 kB~3,5 kB~13 kB (+react-redux)
Downloads/sem. (npm)~5,5 M~1,6 M~4,8 M
Boilerplatemínimobaixomédio-alto
Modelo mentalstore únicoátomosstore + slices
LicençaMITMITMIT

Números coletados em 2026-07-12 (npm registry, npm downloads, bundlephobia). Confira antes de decidir. O ecossistema muda.

Recomendação

Adote Zustand. Para um SPA React 19 de tamanho médio, ele entrega o melhor equilíbrio: bundle irrisório, zero provider e um modelo mental que o time absorve numa tarde. O atrito atual (prop drilling e re-renders) resolve-se com um store + seletores, sem trocar a arquitetura do app.

Reconsidere se: o estado for majoritariamente derivado e granular (Jotai brilha aí), ou se o time já for grande e padronizado em Redux com uso pesado de RTK Query, aí a convenção do Redux Toolkit paga o peso extra.

Plano de prova de conceito

  1. pnpm add zustand e criar src/store/ui.ts com um slice real (ex.: filtros do dashboard). Timebox: 2h
  2. Migrar UMA tela do prop drilling para o store, medindo re-renders com o React DevTools Profiler. Timebox: 3h
  3. Adicionar persistência (persist) só do que precisa sobreviver a reload. Timebox: 1h
  4. Revisão: comparar bundle antes/depois e validar seletores. Timebox: 1h

Riscos e mitigação

RiscoMitigação
Seletores mal feitos re-renderizam demaisLint de seletor + revisão no PR da PoC
Store vira "balde global"Slices por domínio; nada de lógica de servidor no store
Estado de servidor no lugar erradoManter data-fetching em React Query, store só para UI

Critérios de aceite do spike

  • Uma tela migrada com re-renders medidos antes/depois
  • Diferença de bundle documentada
  • Convenção de slices escrita no README do time
  • Decisão registrada (este documento) no repositório