Skip to content

State Management - Gerenciamento de Estado (Zustand)

Biblioteca

O projeto usa Zustand para gerenciamento de estado global. Stores sao criadas com create e consumidas via selectors nos componentes.


Estrutura de Store

typescript
import { create } from 'zustand'

type ContractsState = {
  items: Contract[]
  loading: boolean
  loadContracts: () => Promise<void>
}

export const useContractsStore = create<ContractsState>((set, get) => ({
  items: [],
  loading: false,

  loadContracts: async () => {
    set({ loading: true })
    try {
      const { data } = await getContractsService()
      set({ items: data })
    } finally {
      set({ loading: false })
    }
  },
}))

Consumo nos Componentes

Sempre usar selectors para evitar re-renders desnecessarios:

typescript
const items = useContractsStore((s) => s.items)
const loading = useContractsStore((s) => s.loading)
const loadContracts = useContractsStore((s) => s.loadContracts)

PROIBIDO desestruturar a store inteira:

typescript
const { items, loading } = useContractsStore()

Padrao de Store com Filtros

typescript
type ItemsState = {
  items: Item[]
  total: number
  loading: boolean
  search: string
  status: ItemStatus | 'all'
  loadItems: (params?: ItemFilter) => Promise<void>
  setSearch: (params: ItemFilter) => void
}

export const useItemsStore = create<ItemsState>((set, get) => ({
  items: [],
  total: 0,
  loading: false,
  search: '',
  status: 'all',

  loadItems: async (params) => {
    set({ loading: true })
    try {
      const response = await getItemsService(params)
      set({ items: response.data.data, total: response.data.total })
    } finally {
      set({ loading: false })
    }
  },

  setSearch: (params) => {
    if (params.search !== undefined) {
      set({ search: params.search })
    }

    if (params.status !== undefined) {
      set({ status: params.status })
    }

    get().loadItems(params)
  },
}))

Organizacao

  • Estado Zustand: modules/[modulo]/hooks/use-*.tscreate + hook consumidor no mesmo arquivo (shape em models/[nome]-state.ts)
  • Proibido pasta stores/ em modulos
  • Hooks de tela: modules/[modulo]/hooks/use-*-screen.ts — orquestram side effects (useEffect, callbacks) usando o hook de estado
  • Componentes: consomem o hook consumidor (useItems), nunca useItemsStore direto na view