State management

Escopo: transversal. Aplica-se a qualquer linguagem ou stack do projeto.

State management (gerenciamento de estado) é a disciplina de decidir onde o estado da aplicação vive, quem pode alterá-lo e como as mudanças se propagam para a interface. Em mobile, essa decisão tem peso extra: o estado precisa sobreviver a rotações de tela, process death e retomadas do background, situações que aplicações web raramente enfrentam.

A consequência de uma estratégia de estado mal definida é visível: spinners que nunca somem, formulários que resetam sem motivo, e dados inconsistentes entre telas.

Conceitos fundamentais

ConceitoO que é
UI state (estado da interface)Estado que controla o que está visível: loading, erro, campo de formulário
Domain state (estado de negócio)Dados do domínio: usuário autenticado, lista de pedidos, produto selecionado
Unidirectional data flow (fluxo de dados unidirecional)Estado muda por ações → UI reage às mudanças; nunca o contrário
Reactive (reativo)A UI atualiza automaticamente quando o estado muda, sem atualização manual
ViewModel (modelo da tela)Camada que expõe o estado da tela e processa ações da UI
Single source of truth (fonte única da verdade)Cada dado tem um único dono; cópias são derivadas, nunca independentes
State hoisting (elevação de estado)Mover o estado para o ancestral comum mais próximo que precisa dele
Derived state (estado derivado)Valor calculado a partir de outro estado; nunca armazenado separadamente

UI state vs domain state

A distinção mais importante em state management mobile é separar o estado que controla a tela do estado que representa o domínio. Aqui, UI (User Interface, interface do usuário) é a camada que o usuário vê e toca; domínio é o conjunto de regras e dados de negócio que vivem por trás dela.

UI state é efêmero e pertence à tela:

  • Campo de busca preenchido
  • Indicador de carregamento visível
  • Mensagem de erro exibida
  • Item selecionado em uma lista

Domain state é persistente e pertence ao domínio:

  • Usuário autenticado e seus dados
  • Lista de produtos carregada
  • Carrinho de compras
  • Configurações do usuário

UI state morre com a tela. Domain state sobrevive à navegação e ao process death. Misturar os dois no mesmo lugar produz telas que consomem dados que já foram destruídos ou que persistem lixo desnecessariamente.

Unidirectional data flow

O padrão mais sólido para state management em mobile é o fluxo unidirecional:

Usuário dispara ação → ViewModel processa → Estado atualizado → UI reage

Nunca o contrário. A UI não altera o estado diretamente: dispara uma ação e aguarda a atualização.

BAD: Tela altera o objeto de pedido diretamente ao clicar em "Confirmar"
GOOD: Tela dispara ação "ConfirmarPedido"ViewModel processa → estado atualizado → tela reage

O benefício é rastreabilidade: toda mudança de estado passa por um ponto único, tornando o fluxo previsível e testável.

Reatividade

Em mobile, o padrão reativo é o padrão esperado: a UI observa o estado e atualiza automaticamente quando ele muda. Não existe "chamar refresh manualmente".

Estado muda → observadores notificados → componentes relevantes re-renderizam

Cada framework tem seu mecanismo:

PlataformaMecanismo reativo
Android (Kotlin)StateFlow, LiveData
iOS (Swift)Combine, @Published, @Observable
Flutter (Dart)StreamBuilder, Provider, Riverpod, Bloc
React NativeuseState, useReducer, Zustand

O mecanismo muda, o princípio não: estado → UI, nunca UI → estado.

Onde o estado vive

EscopoOnde armazenarExemplos
Componente únicoEstado local do componenteCampo de texto, toggle local
Tela inteiraViewModel da telaDados da tela, loading, erro
Múltiplas telasEstado compartilhado / storeUsuário autenticado, carrinho
Persiste entre sessõesBanco de dados localPreferências, dados offline

A regra do escopo mínimo: o estado deve viver no nível mais baixo da hierarquia que ainda atende a todos os consumidores. Elevar o estado além do necessário polui camadas que não precisam dele.

Derived state

Estado derivado é qualquer valor que pode ser calculado a partir de outro estado. Nunca armazene estado derivado separadamente. Sincronizá-lo manualmente é uma fonte garantida de inconsistências.

BAD: manter totalDoCarrinho como estado separado e atualizar manualmente a cada item adicionado
GOOD: calcular totalDoCarrinho a partir da lista de itens sempre que a lista mudar

Derived state computado é sempre consistente porque não tem estado próprio para ficar fora de sincronia.

Process death e recuperação de estado

Quando o SO encerra o processo, o UI state volátil é perdido. O usuário espera recuperar o contexto ao retornar.

A estratégia é salvar o estado mínimo necessário para reconstruir a tela:

App vai para background → salvar estado relevante da tela (ex: ID do item selecionado, posição de scroll)
SO encerra processo     → estado volátil perdido
Usuário retorna         → estado restaurado → tela reconstruída a partir do ID salvo

O critério é: salvar o suficiente para que o retorno seja imperceptível para o usuário, não o suficiente para replicar toda a memória em disco.

Desenvolvido por @thiagocajadev · Fork baseado no repositório pmndrs/docs · Poimandres.