Finite State Machines no React: Gerenciado Estados de Forma Elegante

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:

Apr 7, 2025 - 22:35
 0
Finite State Machines no React: Gerenciado Estados de Forma Elegante

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)

)} {state === STATES.ERROR && (

Error loading data!

)}
); }; 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: