Projetos Práticos para Aprender Zustand: Guia Completo para Desenvolvedores React

Projetos Práticos para Aprender Zustand: Guia Completo para Desenvolvedores React






Projetos práticos para aprender Zustand



Zustand • Prática

Projetos práticos para aprender Zustand

Quatro micro-projetos para consolidar conceitos, padrões de uso e boas práticas com Zustand em aplicações React. Conteúdo técnico, direto ao ponto e com exemplos reais.

1) Fundamentos: o que é Zustand e um store básico

Zustand oferece um estado global baseado em hooks com API simples e sem boilerplate. O objetivo deste projeto é demonstrar o conceito central: um store criado com uma função que define o estado e as ações que o modificam, consumidas por componentes através de um hook.

Caso você esteja migrando de soluções com mais boilerplate, a simplicidade de Zustand facilita a adoção gradual e a divisão do estado por domínios sem precisar de provedores complexos.

// Store básico com Zustand
import create from 'zustand';

export const useCounterStore = create((set) => ({
  count: 0,
  increment: () => set((s) => ({ count: s.count + 1 })),
  decrement: () => set((s) => ({ count: s.count - 1 })),
  reset: () => set({ count: 0 })
}));

// Uso em componente React
function Counter() {
  const { count, increment, decrement } = useCounterStore();
  return (
    <div>
      <button onClick={decrement}>-</button>
      <span>{count}</span>
      <button onClick={increment}>+</button>
    </div>
  );
}

Notas rápidas sobre este modelo:

  • State é imutável por padrão; use funções set(state => …) para transformações seguras.
  • Para reduzir re-renders, importe apenas o slice necessário via seletor (state => state.count).
  • Boas práticas: mantenha o store enxuto por domínio (ex.: contador, usuário, UI).

2) Lista de tarefas: estado compartilhado entre componentes

Projetar um conjunto de tarefas que possa ser lido e modificado por diferentes componentes permite observar como Zustand elimina o excesso de props e facilita a composição de UIs reativas.

  • Armazenamento de itens com propriedades básicas (texto, concluído, data).
  • Operações comuns: adicionar, alternar estado, remover, limpar concluidos.
  • Seletores para evitar re-render desnecessário em partes não afetadas.

Exemplo conceitual de store para tarefas (em código conceitual, sem blocos adicionais):

Uso típico com seletores (para reduzir re-renderizações):

// Store de tarefas com seletores
import create from 'zustand';

export const useTodoStore = create((set, get) => ({
  todos: [],
  addTodo: (text) =>
    set((s) => ({
      todos: [...s.todos, { id: Date.now(), text, done: false }]
    })),
  toggleTodo: (id) =>
    set((s) => ({
      todos: s.todos.map((t) => (t.id === id ? { ...t, done: !t.done } : t))
    })),
  removeTodo: (id) =>
    set((s) => ({ todos: s.todos.filter((t) => t.id !== id) })),
  clearDone: () => set((s) => ({ todos: s.todos.filter((t) => !t.done) }))
}));

// Em componente React, subscreva apenas ao que precisa
const todos = useTodoStore((state) => state.todos);

3) Carrinho de compras com persistência local

Gerenciar itens de carrinho em várias telas e recarregar o estado ao retornar à página são cenários comuns. Zustand, com o middleware de persistência, facilita manter o estado entre sessões sem código boilerplate adicional.

  • Itens com id, nome, preço e quantidade.
  • Operações: adicionar, atualizar quantidade, remover, calcular total.
  • Persistência automática em localStorage com chave específica por domínio do app.

Exemplo de store com persistência (configurado com middleware persist):

// Carrinho com persistência
import create from 'zustand';
import { persist } from 'zustand/middleware';

export const useCartStore = create(
  persist((set, get) => ({
    items: [],
    addItem: (item) =>
      set((s) => ({
        items: [...s.items, item]
      })),
    updateQty: (id, qty) =>
      set((s) => ({
        items: s.items.map((it) => (it.id === id ? { ...it, qty } : it))
      })),
    removeItem: (id) =>
      set((s) => ({
        items: s.items.filter((it) => it.id !== id)
      })),
    total: () => get().items.reduce((acc, it) => acc + it.price * it.qty, 0)
  }), { name: 'cart' })
);

4) Painel de métricas com devtools e middleware (advanced)

Para cenários de monitoramento simples, o uso de devtools traz visibilidade sobre ações e mudanças de estado. Com o middleware devtools, é possível inspecionar operações e fazer time-travel debugging durante o desenvolvimento.

  • Devtools registra ações e estados ao longo do tempo.
  • Útil para entender fluxo de dados em respostas a ações do usuário.
  • Combine com seletores para observar apenas as mudanças relevantes para cada componente.

Exemplo rápido de store com devtools:

// Painel de métricas com devtools
import create from 'zustand';
import { devtools } from 'zustand/middleware';

export const useMetricStore = create(
  devtools((set) => ({
    clicks: 0,
    increment: () => set((s) => ({ clicks: s.clicks + 1 })),
    reset: () => set({ clicks: 0 })
  }), { name: 'metric-store' })
);


Curtiu? Explore mais conteúdos técnicos

Este conjunto de projetos serve como ponto de partida para dominar Zustand na prática. Para ampliar seu conhecimento, confira outros posts com foco em padrões de estado, integração com React e melhores práticas.