React Basics — Renderização e Gerenciamento de estados
No artigo de hoje iremos abordar tratamento de estados, como podemos gerenciá-los e como isso afeta as renderizações em uma aplicação.
Estado de um componente, o que é?
Antes de mais nada, vamos definir um componente como sendo uma parte de uma interface. O que seria então, um estado para esse “pedaço de interface”? Para fazer esta definição, iremos utilizar uma analogia com o mundo real, desta forma fica mais fácil de entendermos o significado de um estado.
Vamos supor que estamos em uma sala qualquer e que nesta sala temos um ventilador. Para este cenário, é facil identificarmos o que o ventilador pode fazer, ele pode estar DESLIGADO, ou então, ligado com estas velocidades: MÍNIMA, NORMAL ou MÁXIMA. Perceba que estes são os estados possíveis para o nosso ventilador de exemplo.
A gente sabe que quando alteramos o estado do ventilador ele reage imediatamente a essa mudança, por exemplo, quando mudamos do estado DESLIGADO para o estado MÍNIMO o ventilador imediatamente começa a ventilar com sua potência mínima (uau!).
Diante disso, você deve estar se perguntando, o que um ventilador tem a ver com React.js?
Para o nosso exemplo, tudo!
Como o nosso exemplo representa uma analogia aos estados de um componente React, podemos afirmar que temos um componente chamado Ventilador (observe que a primeira letra é maiúscula) e com um estado que a chamaremos de status (primeira letra minúscula), na qual este estado irá indicar em qual situação o ventilador está em uma determinada instância de tempo.
Ok, nada de mais até aqui, temos um componente Ventilador e um estado chamado status, mas quando alteramos o estado do ventilador ele deveria começar a ventilar, não é mesmo? Então lá vem a pergunta:
Por que e como um componente é renderizado?
Ora, se queremos ligar o ventilador (isto é, alterar o seu estado), é fácil afirmarmos que queremos que aconteça algo com ele, no nosso caso é ventilar na velocidade mínima, ou seja, atualizar nosso componente Ventilador. A frase “atualizar nosso Ventilador” em react nada mais é do que renderizar componente.
Portanto, quais conclusões é possível tirar do parágrafo acima? R: Sempre que um estado é alterado, o componente a que ele pertence é re-renderizado, o mesmo ocorre para propriedades vindas do componente pai, ou seja, quando um componente filho recebe uma props de um componente pai e essa props é alterada, então tanto o componente pai quanto o componente filho são re-renderizados. A imagem abaixo tenta explicar isso de uma forma mais intuitiva.
Este tópico é o coração do react, ele deve ser tratado com muito cuidado pois em aplicações de grande escala pode haver muita perda de desempenho e que consequentemente acabaria diminuindo a qualidade final do produto. Imagine um cenário que exista uma árvore com milhões de ramificações, agora suponha que não exista nenhum tratamento de otimização para esta árvore e se, por algum motivo a raiz dessa árvore sofrer alguma alteração de estado, toda o restante da árvore seria reconstruída, e consequentemente teríamos um gargalo na aplicação. A documentação do react disponibiliza diversos meios para otimizar estes obstáculos, como por exemplo, o uso de técnicas de memoização na qual é utilizada a memória do computador em vez de processamento computacional, porém o foco deste artigo é mostrar apenas conceitos básicos e claro, isso será o tema de outro artigo :)
Até neste ponto já sabemos porque um componente é renderizado e pra que serve um estado. Voltando para o nosso exemplo do ventilador, que tal adicionarmos um componente pai para ele? Quem poderia ser o “pai” do ventilador? Bom, o Ventilador estava em uma Sala, então…
…Após uma análise cirúrgica e bem discutida, decidimos que a Sala também será um componente, e ela será o pai do Ventilador. Tá, mas ainda não faz sentido, como poderíamos integrar um ao outro?
Vamos usar a nossa criatividade, a nossa sala poderia fornecer a energia elétrica necessária para este ventilador, que por sua vez, só funcionaria se o cabo de alimentação estiver conectada a uma rede de energia elétrica. Fazendo isso já teríamos uma árvore react. Uma forma de implementação de tudo que foi dito até agora seria assim:
Lembremos que nosso foco é entender o funcionamento de estados e os motivos da renderização e re-renderização, desta forma podemos ignorar a simplicidade no resultado visual destes dois componentes.
Analisando o componente a nível de código, é possível ver o primeiro componente criado nomeado de Ventilador:
O Ventilador possui algumas funcionalidades bem específicas, sendo elas:
- Recebe por props um valor booleano nomeado de energiaEletrica.
- Em react utilizamos hooks em componentes funcionais para declarar um estado, comumente usando a hook useState. No código acima nomeamos o nosso estado de status e a setamos como DESLIGADO em seu estado inicial. Todas as alterações de um estado utilizando o useState devem ser utilizando a função setter que o useState disponibiliza, este setter é declarado como o segundo item do array que o useState retorna.
- Depois temos as funções que atualizam o estado dependendo da opção que o usuário escolhe para o ventilador.
- Por fim, o componente retorna o JSX que renderiza a tela fazendo uso do estado e apresenta em tela as velocidades que o Ventilador possui.
Agora, temos o componente Sala que disponibiliza a energia elétrica que o ventilador necessita:
A Sala possui algumas responsabilidades destinadas a ela:
- Ela possui um estado que informa se tem ou não energia elétrica disponível.
- Uma função que é chamada quando o evento do botão é acionado, atualizando o estado da energia elétrica para true ou false.
- Por fim, a sala retorna o JSX mostrando o estado da energia elétrica, um botão para alterar o estado dela e o Ventilador que criamos acima, passando o estado da energia elétrica.
Este componente pode ser melhorado utilizando callbacks para atualizar o estado do Ventilador para quando a Sala desligar a energiaEletrica, afinal, não queremos deixar o ventilador ligado sem energia elétrica correto? Isso não faria sentido.
Callbacks são funções que são utilizadas para passar responsabilidades de um nó filho para um nó pai em uma árvore react, fazendo o efeito contrário de injetar um estado de pai para filho, ou seja, é uma forma de conseguir “subir” na árvore, fazendo com que um filho possa re-renderizar um componente pai. Porém este assunto também não é tema deste artigo :(
O componente criado neste artigo é bem simples quando comparado ao que o react consegue fazer, porém como o objetivo é mostrar apenas conceitos básicos para iniciar no React, então não há a necessidade de apresentar tópicos mais sofisticados de desenvolvimento.
Até a próxima!