ReactJS: gerenciando estados com Recoil
Gerenciar os estados de aplicações ReactJS não é tarefa fácil, uma vez que a aplicação começa escalar em tamanho, aumentando sua quantidade de componentes e como consequência os estados que os mesmos carregam, compartilhar e atualizar estes estados se torna uma tarefa complexa.
Aí surgem as bibliotecas para gerenciamento de estados, facilitando uma parte do nosso trabalho.
Então pessoal, bora dar uma olhadinha em uma dessas bibliotecas utilizada para gerenciar estados de aplicações React (Recoil)? Segue o fio…
O que é o Recoil?
Ele é uma biblioteca projetada para gerenciar os estados de aplicações React de forma performática. Foi criado dentro do Facebook e anunciado em maio de 2020 por Dave MacCabe, o pai da criança, no evento ReactEurope. Embora ainda esteja em fase experimental, sua API tem crescido nos últimos tempos e bugs foram corrigidos. A biblioteca é open source, e é mantida pela comunidade neste repositório.
O Recoil surgiu, pois, nenhuma outra solução de gerenciamento de estados podia suprir a demanda por performance que necessitavam naquele período, onde para uma aplicação específica, existia uma grande quantidade de componentes renderizados e que necessitavam ser atualizados separadamente com frequência.
Sua concepção teve como base três premissas:
- Compartilhamento de estado de forma simples de utilizar e modificar;
- Utilização de dados derivados, sejam assíncronos ou síncronos;
- Observabilidade de estado em toda aplicação.
Como funciona?
A ideia foi trazer o controle dos estados para fora da aplicação, assim evitando a necessidade da passagem desses mesmos estados entre componentes que não os utilizam. Isso faz com que quando um estado for alterado a re-renderização aconteça somente nos componentes que de fato o utiliza e não em toda a árvore de componentes.
Aqui temos dois principais conceitos:
- Atoms: são os responsáveis por conter os estados da aplicação;
- Selectors: computam dados de Atoms e retornam um novo valor derivado do estado.
Mãos no código!
Vamos criar uma aplicação simples para conversão de moeda, a fim de pormos em funcionamento esses dois principais conceitos deste gerenciamento de estados.
Criamos o projeto pelo terminal executando:
npx create-react-app currency-converter
Em seguida instalamos o Recoil no nosso projeto:
npm install recoil<br>
No arquivo `src/index.js` vamos colocar o RecoilRoot como elemento pai de nossa aplicação, no caso pai do componente App. O RecoilRoot é o responsável por gerenciar os estados do Recoil, portanto dentro dele podemos utilizar Atoms e Selectors.
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { RecoilRoot } from "recoil";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<RecoilRoot>
<App />
</RecoilRoot>
</React.StrictMode>
);
Agora vamos para o conteúdo do arquivo `src/App.js`
import { atom, selector, useRecoilState } from "recoil";
const exchangeRate = 5.22;
const brlAtom = atom({
key: "brl",
default: 1,
});
const usdSelector = selector({
key: "usd",
get: ({ get }) => {
const brl = get(brlAtom);
return brl * exchangeRate;
},
set: ({ set }, newUsdValue) => {
const newBrlValue = newUsdValue / exchangeRate;
set(brlAtom, newBrlValue);
},
});
function App() {
const [brl, setBrl] = useRecoilState(brlAtom);
const [usd, setUsd] = useRecoilState(usdSelector);
return (
<div className="App">
<h1>Conversor de moeda</h1>
<div>
<label htmlFor="brl">BRL:</label>
<input
id="brl"
type="number"
value={brl}
onInput={(e) => {
setBrl(e.target.value);
}}
/>
<label htmlFor="usd">USD:</label>
<input
id="usd"
type="number"
value={usd}
onInput={(e) => {
setUsd(e.target.value);
}}
/>
</div>
</div>
);
}
export default App;
Aqui podemos ver como é muito similar a utilização de estados do Recoil com o useState
do React, apenas usamos o hook useRecoilState
, ele nos traz o valor e um callback para setar o valor do estado. A diferença é que no Recoil o estado fica disponível para todos os componentes presentes dentro do RecoilRoot
.
Neste exemplo utilizamos um Atom (brlAtom
) o qual é a nossa fonte da verdade, nele está o estado da aplicação em si, e criamos um Selector (usdSelector
) que faz a conversão da moeda de BRL para USD, utilizando o valor de troca e o valor do estado como cálculo.
Podemos ver que no Selector também conseguimos atribuir valor com a propriedade `set
`, nos possibilitando adequar o valor do estado em brlAtom
. Então, quando mexemos no valor de qualquer um dos dois inputs o outro é ajustado.
Conclusão
Bom, se chegaram até aqui acabou haha, demos uma breve pincelada no Recoil, falamos um pouco sobre sua história e aplicamos seus dois principais conceitos (Atoms / Selectors) de maneira bem sucinta.
Existem outras funcionalidades mais avançadas presentes nesta biblioteca de gerenciamento de estados, tais como AtomFamily e SelectorFamily, e acredito estar por vir novidades por aí, pois, ela continua sendo aprimorada.
E é sobre isso galera, caso queiram se aprofundar mais seguem alguns materiais sobre:
Vlews… Flows… 😁