Gestión de Estado Complejo con useReducer en React

Clase 15 de 31Curso de React Avanzado

Resumen

Domina la gestión de estado local complejo en React con useReducer y TypeScript mientras construyes un emoji todo list. Verás cuándo useState se queda corto, cómo se coordinan estado, acciones y reducer, y cómo tipar datos clave para agregar y eliminar elementos de forma clara y mantenible.

UseReducer en una lista de emojis tipo todo

Antes de escribir código, se plantea un flujo simple y potente: un input donde escribes "eat", "sleep" o "exercise", presionas Enter y se renderiza el emoji correspondiente; al hacer clic sobre un ítem, se elimina. Este comportamiento requiere leer y modificar estado de manera segura, algo que useReducer resuelve con una arquitectura explícita.

¿Por qué useState se queda corto para listas complejas?

  • Agregar, eliminar y actualizar implica múltiples funciones y estados derivados.
  • La lógica se dispersa y crece el riesgo de errores.
  • useReducer centraliza la lógica: una sola puerta para mutar el estado.

¿Qué interacción tendrá el usuario en la UI?

  • Escribe un texto como "eat" y presiona Enter.
  • El texto se convierte en emoji y se agrega a la lista.
  • Haz clic sobre un emoji para eliminarlo.
  • El flujo es inmediato y claro para tareas completadas.

Actores del estado y su flujo de comunicación

Para un manejo robusto se definen tres actores: estado, acciones y reducer. Esta separación facilita razonar sobre qué se guarda, qué se quiere hacer y cómo se transforma el estado.

¿Qué representa cada actor en useReducer?

  • Estado: bolsa o maleta con toda la información. Inicia como estado inicial vacío.
  • Acciones: instrucciones como "add" y "remove" que describen la intención.
  • Reducer: la función que decide cómo agregar o eliminar en el estado.

¿Cómo se comunican componente, acción y reducer?

  • El componente solo lee del estado para renderizar la UI.
  • El componente no modifica el estado directamente.
  • El componente expresa una intención: agregar o eliminar.
  • Esa intención se envía como acción con un payload.
  • El reducer es el único que modifica el estado.
  • Tras el cambio, el componente vuelve a leer y renderiza.

¿Qué casos de uso cubren las acciones add y remove?

  • Agregar: crea un nuevo todo a partir del texto ingresado.
  • Eliminar: remueve un todo por su ID, típico con filter sobre el array.
  • Ambas acciones mantienen la lógica concentrada en el reducer.

Tipos en TypeScript y configuración del proyecto

Definir tipos primero ordena el pensamiento: se clarifica la forma de los datos, entradas y salidas. Aquí se tipan el todo, el state, las action y el estado inicial.

¿Cómo declarar los tipos state, todo y action?

// Forma de un todo
type todo = {
  id: number;
  text: string;
};

// Estado general
type state = {
  todos: todo[];
};

// Acciones permitidas
type action =
  | { type: 'add_todo'; payload: string }
  | { type: 'remove'; payload: number };
  • todo: usa un id numérico para identificar y eliminar.
  • state: almacena un arreglo de todos.
  • action: describe la intención y el payload que necesita cada caso.

¿Cómo se define el estado inicial tipado?

const initialState: state = {
  todos: [],
};
  • Arranca vacío para ir "llenando la maleta" con nuevos todos.
  • El tipado evita inconsistencias al manipular el estado.

¿Cómo crear el proyecto con Vite y React TypeScript?

  • Crea el proyecto con Vite y selecciona React + TypeScript.
  • Instala dependencias y corre el servidor.
  • Crea el componente en src/components/todoList.tsx.
npm create vite@latest
# Nombre: MyUseReducerApp
# Plantilla: React + TypeScript
cd MyUseReducerApp
npm install
npm run dev
  • Estructura inicial lista para añadir el reducer y despachar acciones.
  • Próximo paso: implementar el reducer y el dispatch desde el componente.

¿Te gustaría ver el reducer en acción y el mapeo de texto a emoji paso a paso? Deja tus dudas o ideas en los comentarios.