Máquinas de Estado en Desarrollo Web: Configuración y Uso Práctico

Clase 23 de 31Curso de React Avanzado

Contenido del curso

Patrones de renderizado y composición

Manejo del estado en React

Resumen

Representar formularios con múltiples pasos en una aplicación web puede volverse caótico si no se cuenta con un modelo claro para gestionar las transiciones entre vistas. Las máquinas de estado ofrecen exactamente esa estructura: un sistema que define estados, transiciones y condiciones para moverse entre ellos de forma predecible y organizada.

¿Qué es una máquina de estado y por qué usarla en desarrollo web?

Una máquina de estado es un modelo que permite representar un sistema con varios estados y definir cómo se transita de uno a otro mediante acciones específicas [0:10]. Imaginemos tres estados en una aplicación: solo uno es visible a la vez, y para pasar al siguiente debe cumplirse una condición, como completar un formulario.

Este patrón es especialmente útil en formularios de tipo wizard, es decir, formularios divididos en pasos secuenciales [0:42]. Por ejemplo:

  • Paso 1: el usuario ingresa su nombre.
  • Paso 2: el usuario ingresa su edad.
  • Paso 3: una pantalla de confirmación muestra los datos recopilados.

Cada paso funciona como un estado independiente. La transición entre ellos depende de que la información del paso actual esté completa. Si el formulario no se ha llenado correctamente, el usuario no puede avanzar. Este mecanismo actúa como un blocker que protege la integridad del flujo [0:34].

¿Cómo se configura la máquina de estado con TypeScript?

El primer paso es crear un proyecto con Vite, seleccionando React y TypeScript como tecnología base [2:28]. Una vez configurado el entorno, se define una interfaz llamada StateMachineConfig que estructura toda la máquina.

¿Qué propiedades necesita la configuración?

La interfaz contempla tres propiedades fundamentales [2:55]:

  • initialStep: indica cuál es el paso inicial del formulario, por ejemplo, el campo donde se solicita el nombre.
  • steps: un objeto donde cada key representa un paso. Cada paso contiene una función advance que retorna un booleano indicando si el usuario puede continuar o no [3:30].
  • views: un objeto que asocia cada key con el componente de React que debe renderizarse en ese paso [4:05].

La función advance recibe el estado actual como parámetro. Cuando la información almacenada está completa, retorna true y la máquina permite la transición al siguiente estado.

¿Cómo se definen los tipos para cada paso?

Se crea un tipo llamado StepNames que enumera los nombres posibles de cada paso mediante un union type [5:00]:

typescript type StepNames = "step1" | "step2" | "confirmation";

Este tipo se utiliza tanto para initialStep como para las keys de steps y views, garantizando que solo se usen nombres válidos en toda la configuración.

La interfaz StateMachineConfig recibe genéricos para el tipo de estado y los nombres de los pasos [5:35]:

typescript interface StateMachineConfig<StateType, StepNames extends string> { initialStep: StepNames; steps: { [key in StepNames]: { advance: (state: StateType) => boolean; }; }; views: { [key in StepNames]: React.ComponentType; }; }

Dentro de views, cada entrada devuelve un React.ComponentType, es decir, un componente que recibe el estado y un setState de tipo React.Dispatch<React.SetStateAction<StateType>> para leer y modificar la información del formulario [5:50].

¿Cómo se modela el estado del formulario wizard?

Finalmente, se define un tipo que representa los datos que el formulario recopila a lo largo de sus pasos [6:30]:

typescript type WizardState = { name: string; age: number; };

El campo name se captura en el primer paso y age en el segundo. El paso de confirmación simplemente lee ambos valores y los presenta al usuario.

¿Cuál es el siguiente paso para completar el formulario wizard?

Hasta este punto se han establecido las bases tipadas de la máquina de estado: los nombres de los pasos, la estructura de configuración con genéricos y el modelo de datos del formulario. La siguiente etapa consiste en crear la configuración concreta con los componentes a renderizar y la lógica de validación en cada transición [7:05].

Si ya has trabajado con formularios multipaso y los has manejado con condicionales dispersos, te invitamos a compartir cómo resolviste ese problema y si consideras que este enfoque basado en máquinas de estado simplificaría tu código.