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:

Image description


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! 🚀