MobX — facilitando o dia a dia com React

Rodolpho Rodrigues
b2w engineering
Published in
7 min readOct 1, 2020

É possível afirmar que na B2W as palavras que definem o dia o dia de muitas equipes de desenvolvimento é autonomia e liberdade.

No processo de desenvolvimento de software da nova versão do BSeller, nosso ERP e BackOffice, responsável por controlar e automatizar as operações de e-commerce dos nossos clientes, a diversidade de tecnologias é sempre levada em consideração, com a consciência de que não existe bala de prata, mas sim boa engenharia.

Quando começamos a arquitetar essa nova versão, nos deparamos com dezenas de tecnologias que poderíamos utilizar dentro do nosso contexto. Através de muita análise e PoC, optamos por utilizar o React para construção da nova interface, para nos dar flexibilidade no processo e no ciclo de vida de desenvolvimento.

O MobX foi a solução de gerenciamento de estado que nos chamou atenção pela sua simplicidade, performance, robustez e baixa curva de aprendizado. Não só por se integrar facilmente com React, mas também por lidar com programação reativa de uma forma elegante, simples e expressiva.

Ao longo do desenvolvimento com essa biblioteca, fomos notando a cada funcionalidade adicionada, a cada componente implementado e em como eles se relacionam, que a decisão havia sido acertada dentro do nosso contexto.

O que é MobX?

MobX é uma biblioteca que torna o gerenciamento de estado simples e escalável, aplicando de forma transparente a programação reativa funcional.

Por ser standalone, pode ser utilizado tanto do lado do cliente quanto do servidor, integrando-se a diversas arquiteturas e design de sistema, .

Principais conceitos por trás do MobX

Qualquer coisa que possa ser derivada do estado do aplicativo deve ser derivada. Automaticamente!

Mobx concept

MobX suporta um fluxo de dados unidirecional, onde as ações alteram o estado, que por sua vez atualiza todos os componentes afetados pela mudança de estado.

Vamos definir os principais conceitos:

  1. Observable values: qualquer valor que pode sofrer mutação e servir como fonte para computed values, é um estado. MobX pode tornar a maioria dos tipos ( primitivos, arrays, classes, objetos, etc ) como dados observáveis;
  2. Computed values: qualquer valor pode ser calculado e derivado através de uma função que opera outros valores observáveis. Como computed values também são valores observáveis, até mesmo a renderização de uma interface pode ser completamente derivada de um estado observável. Computed values podem variar desde uma simples concatenação de strings até a visualização de objetos complexos. Funções que retornam valores derivados sempre devem ser puras;
  3. Reactions: uma reação pode se considerar semelhante a um computed value, mas ao invés de gerar um novo valor, é produzido um efeito colateral. Ela conecta a programação reativa e imperativa para tarefas como fazer requisições de rede, imprimir no console, atualizar a árvore de componentes do React, etc;
  4. Actions: são o principal meio de alterar o estado da aplicação. Não são um reação às mudanças de estado, mas usam, por exemplo, eventos do usuário para modificar o estado observável.

Quando o estado é alterado, todas as ações são atualizadas automaticamente, atomicamente e de forma síncrona. Isto significa que as actions podem inspecionar com segurança um computed value diretamente, após o estado ser alterado.

Os computed values são atualizados usando a estratégia lazy, onde qualquer valor que não esteja ativamente em uso não será atualizado ou seja, se algum componente não estiver mais sendo utilizado, ele será coletado automaticamente pelo garbage collector.

Reatividade na prática com MobX

React ❤ MobX

React e MobX juntos são uma combinação poderosa. Ambos fornecem soluções otimizadas e exclusivas para problemas comuns no desenvolvimento de aplicações, sem contar na diminuição considerável de boilerplate.

O React renderiza a interface de usuário da melhor maneira possível, usando o Virtual DOM que reduz o número de mutações custosas do próprio DOM.

O MobX detém de mecanismos para otimizar a sincronização de estado da aplicação, com os componentes React usando um gráfico de estado de dependência virtual reativo, atualizado apenas quando estritamente necessário.

Observer e Observable

Para tornar os dados reativos na programação tradicional, muitas vezes utilizamos o padrão observer. Esse padrão consiste em um objeto observable que mantém uma lista de assinantes chamados observers. Quando os dados do objeto observable mudam, ele se encarrega de notificar todos seus observers assinantes, causando assim uma reação.

Embora o conceito seja simples, na prática este padrão pode ser complicado de ser implementado, pois cada observer precisa se inscrever e cancelar manualmente o observable.

O MobX facilita muito esse trabalho, adicionando automaticamente a lógica de observer e observable usando anotações ( decorators ) e também através da função decorate , caso o seu sistema não suporte uso da sintaxe de decorators.

Tornando o React reativo

Até o momento tudo parece um tanto acadêmico, então vamos tornar as coisas mais concretas.

O código desenvolvido pode ser encontrado neste perfil do codesandbox.

Foi preparado um exemplo com uma lista de Todos — acredite. Para deixar os exemplos um pouco mais atrativos, estilizei alguns componentes com a biblioteca styled-components.

Exclusivamente para fins didáticos, teremos duas classes que manterão o estado da nossa aplicação, a classe Todo e a classe TodoList .

Para declarar uma propriedade como observável, use a anotação @observable

Neste exemplo, estamos declarando algumas propriedades como observáveis. Sendo assim, qualquer observador que estiver utilizando uma propriedade observável será notificado quando o estado delas for alterado.

Agora que declaramos nossas propriedades observable, vamos declarar as actions, que serão, de forma declarativa, as funções responsáveis por alterar os valores das propriedades observable.

Actions devem ser utilizadas em funções que alteram estado. Repare como esta explícito onde o estado da aplicação é alterado, através dos métodos anotados com @action .

O método Todo#toggle() esta anotado com @action.bound.Isso indica que o bind será feito automaticamente, sendo útil caso a referência de toggle seja passada para um escopo diferente e seu this seja sempre do objeto de origem, ou seja, apontando sempre para a instância da classe Todo .

Com o nosso domínio já implementado, podemos ver que MobX e React funcionam muito bem juntos, conforme mostrado no exemplo a seguir:

Neste componente, podemos ver em especial o uso do HOC (Higher-Order Component) observer, que faz com que todo o componente se torne um observador que reage as alterações dos dados observáveis causando assim uma nova renderização. Importante ressaltar que também é possível tornar componentes de classe como observadores através da anotação @observer .

O mesmo ocorre no componente TodoListView fazendo uso observer , que provocará uma nova renderização quando o usuário informar que um Todo foi ou não concluído (alterando estado de Todo#done através do método Todo#toggle()), ou quando uma nova tarefa for adicionada:

O comportamento pode ser visto na demonstração abaixo:

Valores derivados de valores observáveis

MobX permite criar valores a partir da mudança de estado de dados observáveis, ou seja, é possível gerar um valor a partir de outro valor observável, simplesmente utilizando da anotação @computed .

Este é um recurso poderoso, que nos permite combinar unidades básicas com a finalidade de gerar unidades mais complexas.

Utilizando de computed values, o MobX memoriza o resultado calculado, ou seja, quando o cálculo for realizado, ele fará uma comparação profunda para ver se o resultado de saída é o mesmo que o resultado anterior. Se for, os observadores não serão executados novamente.

Vamos implementar esta técnica na nossa classe TodoList, a fim de nos ajudar a apresentar ao usuário quantos Todos estão pendentes e quantos já foram concluídos.

Como Todo#done e TodoList#todos são propriedades anotadas com @observable, quando alguma (ou ambas) for atualizada, as funções anotadas com @computed que utilizam dessas propriedades gerará um valor derivado delas, ou seja, o método pending retornará o total de Todos pendentes e completed o total de Todos completos.

Resumindo, o componente TodoForm sofrerá uma nova renderização, quando o estado de um Todo for alterado pelo usuário ou quando um novo Todo for adicionado na lista de Todos.

O comportamento pode ser vista na demonstração abaixo:

Reactions

MobX lida com a programação reativa de forma elegante, através das funções autorun , reaction e when . São funções que realizam procedimentos quando o estado de algum dado observável é alterado.

Para exemplificar, vamos usar a função autorun . Esta função recebe uma única função como argumento, que é executada sempre quando os dados são alterados.

Podemos, por exemplo, dizer para salvarmos nossa lista de Todos no localStorage sempre que o estado da lista for alterado:

MobX está agindo efetivamente, ou seja, você alterou alguns dados e então é reavaliada a forma como se usa esses dados. Essa é a essência da programação reativa.

Conclusão

Como apresentado, o MobX se propõe a mostrar uma forma diferente da tradicional de implementar gerenciamento de estado no React, utilizando fortemente os conceitos e técnicas da programação reativa, muito bem declaradas no código.

A diminuição significativa de boilerplate, a simplicidade com que tornamos nossos componentes reativos a mudança de estado, as funções utilitárias que nos auxilia a implementar programação reativa dentre outros fatores fazem do MobX uma alternativa a ser considerada.

Você pode se aprofundar mais nos conceitos do MobX, lendo a documentação no site oficial. Existem muitas outras coisas que a tecnologia fornece e não foram citadas no texto.

--

--

Rodolpho Rodrigues
b2w engineering

Full Stack Developer @ B2W . The passionate programmer