Contenido del curso

Patrones de renderizado y composición

Manejo del estado en React

Cómo construir un reducer con useReducer

Resumen

Aprender a construir un reducer con useReducer en React y TypeScript te permite manejar estados complejos de forma predecible. Aquí verás cómo crear la función que agrega y elimina emojis en un todo list, usando switch case, destructuring y tipado estricto.

Este recurso es ideal para desarrolladores frontend que ya conocen useState y quieren dar el siguiente paso hacia patrones más escalables de manejo de estado.

¿Qué es un reducer y para qué sirve en React?

Un reducer es una función que recibe el estado actual y una acción, y devuelve un nuevo estado. En el minuto [0:11] se introduce como la pieza encargada de modificar el initialState que se creó en la clase anterior.

La idea es centralizar la lógica: en lugar de tener varios setState dispersos, tienes una sola función que decide qué hacer según el tipo de acción que reciba.

¿Qué hace un reducer en React? Recibe el estado anterior y una acción, evalúa el tipo de acción y retorna un nuevo estado sin mutar el original.

¿Cómo estructurar el todoReducer con switch case?

La función se declara como una constante llamada todoReducer y dentro se usa un switch que evalúa action.type. Esto se explica desde el minuto [0:55], donde se compara el uso de un condicional tradicional con el de un switch case, eligiendo este último por claridad cuando hay múltiples acciones posibles.

Los parámetros que recibe la función son dos:

  • El state, tipado con la interfaz State creada previamente.
  • La action, tipada con la interfaz Action que contiene type y payload.

Con esto, TypeScript ya sabe qué propiedades existen y te autocompleta el código mientras escribes.

¿Cómo agregar un nuevo todo al estado?

En el caso addTodo, alrededor del minuto [1:50], se retorna un objeto que conserva el estado anterior usando destructuring (...state) y reemplaza el array de todos con uno nuevo que incluye el elemento agregado.

La lógica concreta es:

  1. Crear una constante newTodo de tipo Todo con dos propiedades: id y text.
  2. El text se obtiene del payload de la acción, es decir, lo que el usuario escribió en el input.
  3. El id se calcula automáticamente sumando uno a la cantidad actual de elementos en state.todos, evitando que el usuario tenga que asignarlo manualmente.

El retorno final concatena el array existente con el nuevo elemento: [...state.todos, newTodo]. Así no se borra nada de lo que ya estaba.

¿Cómo eliminar un todo usando filter?

Para el caso removeTodo, visto hacia el minuto [4:30], se aplica el método filter sobre el array de todos. La condición compara el id de cada elemento con el payload de la acción y conserva solo aquellos cuyo id sea diferente.

En código se ve así: state.todos.filter(todo => todo.id !== action.payload). Es una forma limpia de eliminar sin mutar el array original, respetando el principio de inmutabilidad que React necesita para detectar cambios.

¿Por qué incluir un caso default en el reducer?

El bloque default retorna el estado tal como llegó, sin modificarlo. Esto previene errores cuando se despacha una acción que no coincide con ningún caso definido y mantiene la función pura.

¿Qué pasa si no agrego un default en el switch? El reducer podría retornar undefined ante acciones no reconocidas, rompiendo el estado de tu componente. El default protege esa situación.

¿Cómo mapear texto a emojis con TypeScript?

Después del reducer, se construye un objeto llamado emojiMap que asocia palabras clave con su emoji correspondiente. Por ejemplo, eat se vincula con una hamburguesa y exercise con un emoji deportivo.

El tipado de este objeto es clave para que TypeScript no se queje. Se define como un objeto con index signature:

ts const emojiMap: { [key: string]: string } = { eat: "🍔", exercise: "🏋️" }

Esto le dice al compilador que las llaves serán strings y los valores también serán strings. Puedes ampliar el mapeo con cualquier palabra y emoji que quieras, o incluso reemplazarlos por otros símbolos si tu aplicación lo requiere.

¿Qué conceptos técnicos repasaste en esta práctica?

Varios patrones importantes aparecieron mientras se construía el reducer:

  • Destructuring con ...state para preservar propiedades existentes [2:30].
  • Tipado de parámetros con interfaces State, Action y Todo [1:30].
  • Generación automática de IDs basada en la longitud del array [3:40].
  • Inmutabilidad al retornar siempre nuevos objetos y arrays.
  • Filter como método no mutador para eliminar elementos [4:50].

El siguiente paso será crear el componente que despache estas acciones desde un input real, conectando la interfaz visual con la lógica del reducer para ver el emoji todo list funcionando con useReducer.

¿Ya intentaste implementar tu propio reducer con un mapeo distinto? Cuéntame en los comentarios qué casos agregaste a tu switch.