Gerenciar estados complexos no React pode rapidamente se tornar um desafio, especialmente quando lidamos com múltiplas transições e regras de fluxo. Uma abordagem poderosa para resolver esse problema é o uso de Finite State Machines (FSMs), que ajudam a estruturar estados e transições de maneira previsível e fácil de manter.
Neste artigo, vamos explorar o conceito de FSMs, entender como elas podem melhorar nosso código e criar uma implementação prática sem o uso de bibliotecas externas.
O que são Finite State Machines?
São modelos matemáticos que definem um sistema baseado em estados finitos e suas transições. De forma simples, um componente pode estar em um único estado por vez e só pode mudar para um novo estado através de uma transição definida.
Vamos usar uma situação em que temos uma interface que nela contém um componente de card que faz uma requisição para uma api que retorna os dados para serem exibidos:
- Estado 1:
erro
(em casos que a api falha) - Estado 2:
carregando
- Estado 3:
sucesso
As transições entre os estados estão bem definidas:
- Se a requisição falhar, mudamos para
erro
e podemos exibir uma mensagem de erro. - Em caso de não falha, mudamos o estado para
carregando
. - Se a requisição for bem-sucedida, mudamos para
sucesso
e exibimos os dados.
Essa previsibilidade evita estados inesperados e facilita a manutenção do código.
Visualizando a FSM
A imagem abaixo ilustra a máquina de estados finitos para esse cenário de busca:
Quais os benefícios de usarmos as FSMs no React?
✅ Previsibilidade: Cada estado e transição são claramente definidos, reduzindo erros inesperados.
✅ Facilidade de Depuração: Como todas as mudanças de estados são controladas, fica mais fácil de entender e depurar bugs.
✅ Melhoria na Manutenção: Componentes tornam-se mais organizados, facilitando a leitura e evolução do código.
✅ Melhor Controle de Fluxo: Evita estados inválidos, garantindo que o componente sempre esteja em uma condição válida.
Implementando uma FSM no React com useReducer!
Aqui está um componente aonde utilizamos o useReducer para controlar os estados:
import { useEffect, useReducer } from "react";
import { reducer } from "../utils/reducer";
import { ACTIONS, STATES } from "../utils/constants";
import './DataCard.css';
const DataCard = () => {
const [state, dispatch] = useReducer(reducer, STATES.LOADING);
useEffect(() => {
if (state === STATES.LOADING) {
const timeout = setTimeout(() => {
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => {
if (!response.ok) throw new Error('Failed to fetch');
return response.json();
})
.then(() => dispatch(ACTIONS.SUCCESS))
.catch(() => dispatch(ACTIONS.ERROR));
}, 2000);
return () => clearTimeout(timeout);
}
}, [state]);
return (
{state === STATES.LOADING && Loading card...}
{state === STATES.SUCCESS && (
FSMs
Simulated API content (request successful)
dispatch(ACTIONS.LOAD)}>Reload
)}
{state === STATES.ERROR && (
Error loading data!
dispatch(ACTIONS.LOAD)}>Try again
)}
);
};
export { DataCard };
Teste na Prática!
Quer ver o conceito de FSMs funcionando na prática? Criei um repositório para que você possa clonar e testar por conta própria. Acesse o repositório no GitHub e siga as instruções:
🔗 Repositório FSM React
git clone https://github.com/judsonkerller/fsm-react.git
cd fsm-react
npm install
npm start
Experimente fazer alterações no código e observe como os estados e transições são gerenciados!
Conclusão
Finite State Machines são uma ferramenta poderosa para gerenciar estados de forma estruturada no React. Com bibliotecas como o XState ou implementações manuais usando useReducer
, podemos tornar nosso código mais previsível, modular e fácil de testar.
E aí, já usou FSMs em seus projetos? Se sim, como foi a experiência? Se não, pretende experimentar? Me conta nos comentários! 🚀