Sobre React, Preact, Flux e Hooks

​Programação reativa dominou o cenário front-end, mas não é sobre um motor de templates html mais eficiente, é sobre pensar o fluxo das aplicações de forma muito diferente, compreendendo melhor o tráfego de dados entre as interfaces.

Neste artigo apresento minha revisão dos fundamentos que originaram o React e o Redux, com um olhar conceitual, sobrevoando alguns termos relacionados ao ecossistema React.

Gestão de Estado – Flux

Tenho um software em produção rodando com Vuex (implementação de estado semelhante ao Flux, para o Vue) em um projeto. Ele está fundamentado no Flux, muito atrelado ao React e Redux. Estas anotações focam em compreender a gestão de estado em aplicações front-end modernas.

No vídeo inicial da página do Vuex, na seção “What is Vuex?” o autor explica o funcionamento do Vuex que está baseado:

  • Ser uma única fonte de dados de todas as Views;
  • Ter um sistema de ações (actions) que disparam mudanças nesta fonte dados;
  • Ter um sistema de reatividade, que permite às Views mudarem quando os dados mudam (sem se importar sobre quem executou ou quando a ação foi executada).

No site original do Facebook/Flux, há um vídeo de uma engenheira de software explicando como eles chegaram no conceito do Flux:

Sobre como surgiu o conceito Flux

O vídeo é curto e ela explica o problema no chat do Facebook que originou a busca por uma nova forma de trabalhar.

Basicamente, o problemas chave era a via de mão dupla, onde ao alterar os modelos, eles tinham que alterar as views e ao alterar uma view, os modelos tinham que ser atualizados. O potencial de gerar loops e problemas de performance em geral é grande. É um modelo um tanto óbvio e fácil de programar no início, mas que gera muita dificuldade depois, fortemente imperativo.

Uma das principais linhas de solução foi converter o fluxo para um fluxo de mão única.

Uma metáfora (o trânsito)

Podemos pensar como uma rua muito movimentada que tem duas direções. Os carros entram em diversas vielas paralelas, isso vai atrasando o fluxo dos demais carros que precisam parar para que os demais veículos atravessem.

A secretaria de trânsito da cidade opta por transformar aquela via em uma via de mão única e transforma uma via paralela em via de mão única no sentido oposto.

Inicialmente, há grande irritação (a tal burocracia que a turma não gosta tanto), pois o caminho para se chegar aonde se deseja já não é tão “direto”, se faz necessário executar um caminho mais burocrático, mas que por outro lado, garante um ótimo fluxo nas vias, onde para a maior parte dos carros, o tempo médio de movimentação de um ponto a outro, diminui.

A mudança no fluxo

Metáforas tem limites, e esta aqui foi apenas para ilustrar o tema da palestra, no qual saímos de um fluxo de “vai e vem” (observem as setas em laranja) em direção a um fluxo unidirecional.

https://soft.konscia.floripa.br/sites/default/files/inline-images/pasted%20image%200.png
sobre a tal “via de mão dupla”

E ocorre a mudança para um fluxo de uma única direção, onde as “Views” disparam actions para mudar os dados, o que na metáfora do trânsito, equivale a dar a volta lá na frente.

https://soft.konscia.floripa.br/sites/default/files/inline-images/pasted%20image%201.png
sobre a tal “via de mão única”

A minha conclusão geral com esta primeira parte é o velho princípio de separação de camadas, mas combinado com um entendimento de fluxo, de “direção” que o sistema percorre.

A separação de camadas já existia estratégias Model-View-Controler, mas esta visão de fluxo do sistema em via única, é revolucionária.

A Reatividade

Mas esse é apenas um dos temas, porque este modelo, sem a “reatividade” das Views aos dados, seria inviável. Como saber se os dados mudaram?

Em uma arquitetura front-end mais primitiva, os próprios “controllers” ou “handlers” teriam métodos que logo após alterar os dados, chamariam as instâncias das views e altera os dados da mesma com chamada de métodos. Semelhante a esse slide:

https://soft.konscia.floripa.br/sites/default/files/inline-images/pasted%20image%202.png
código imperativo tradicional

Outro modelo, representado pelo Backbone.js por exemplo, trabalhava com eventos específicos nos dados que podíamos observar para identificar se um modelo ou coleção foi alterada. Assim, as Views observavam determinados modelos para executar alguma operação:

https://soft.konscia.floripa.br/sites/default/files/inline-images/pasted%20image%204.png
Exemplo de código com Backbone

Esse modelo com eventos sobre modelos de dados e coleções já era bom, mas exigia uma programação imperativa diretamente no DOM para mudar algo. Agora, quando uma mesma visualização dependia de um conjunto mais variado de dados, geralmente a orquestração destas soluções ficava complexa.

https://soft.konscia.floripa.br/sites/default/files/inline-images/pasted%20image%205.png
renderização imperativa

A reatividade (ou o React) eliminou do desenvolvedor a necessidade de decidir quando alterar uma view, basta criar o componente e, declarativamente, e mudar os dados, que o React (Preact, etc) se encarrega de fazer as alterações no DOM. Então, o ideal é sempre “renderizar tudo de novo”.

Na análise lógica de quem programou imperativo muito tempo, isso não faria sentido nenhum em tempos de performance, mas novas técnicas utilizando o DOM Virtual tornaram isso possível.

https://soft.konscia.floripa.br/sites/default/files/inline-images/pasted%20image%206.png
re-renderizando

Hooks – Comportamentos como cidadãos de primeira classe

Neste momento em que escrevo, 29 de abril de 2020, faz pouco sentido atuar com front-end reativo sem usar Hooks, que basicamente, é uma forma mais associada ao paradigma funcional de escrever código e ao que tudo indica, harmoniza muito mais com a programação reativa do que a orientação a objetos que se praticava até então.

O contato com os criadores de uma ideia é sempre um bom começo, neste vídeo, Sophie, Dan e Ryan mostram o problema que havia com a abordagem anterior, a solução encontrada com Hooks e por fim, um exemplo mais complexo do mundo real:

O próprio Dan Abramov traz uma versão escrita sobre Hooks e seus motivos neste excelente artigo:

A abordagem de hooks é muito diferente e certamente é boa. Hooks permitem a programação de “comportamentos” que afetam estado e consequentemente geram efeitos colaterais em componentes.

Menção especial: Preact

A partir da sugestão de um grande programador da equipe, estamos utilizando Preact ao invés de React em alguns projetos. Preact implementa a mesma API conceitual do React, mas de forma compacta, mais focada no “core”. Uma das grandes vantagens é que é muito mais simples e leve para integrar com projetos já existentes, já implementa hooks e é pequena.

Gosto disso também para me manter de certa forma concentrado no core da aplicação e não me envolver exageradamente no ecossistema React sem necessidade.

Notas Finais

Antes, era comum uma arquitetura com modelos, controles e views.

Hoje temos arquiteturas com estado, hooks e componentes.

Soa parecido, mas não é. Assim como duas ruas são diferentes dependendo do fluxo dos veículos. A maneira como os dados percorrem o caminho até serem exibidos mudou muito.

Ainda acho que quando estamos programando reativo, com ou sem hooks, desatentos ao estado da aplicação a tendência é um front-end que mais cedo ou mais tarde vai recair sobre os mesmos problemas de antes.

A chave me parece ser ter a clareza sobre o fluxo de dados da aplicação.