Contenido del curso

Herramientas avanzadas: escalabilidad, organización y persistencia

Completar y eliminar to-dos con eventos React

Resumen

Marcar una tarea como completada o eliminarla con un clic es lo que separa una lista estática de una aplicación viva. Acá vas a aprender cómo manejar eventos en componentes hijos de React usando funciones encapsuladas, manipulación de arrays y el actualizador de estado setTodos para que tu to-do app reaccione a cada interacción del usuario.

Cómo disparar un evento onClick desde un componente hijo en React

El primer paso para completar un to-do es decidir dónde vive la lógica. Y aquí viene la decisión clave: el componente TodoItem no debería preocuparse por filtrar arrays ni recalcular estados.

En lugar de pasarle el actualizador global setTodos a cada to-do item, le pasamos una propiedad más específica llamada onComplete. Esto se siente como un evento natural: cuando el usuario hace clic en el ícono de check, el componente solo dispara props.onComplete y listo. Toda la lógica pesada se queda en el componente padre.

¿Por qué no pasar setTodos directamente al componente hijo? Porque obligarías a TodoItem a conocer la estructura completa del estado y a hacer cálculos que no le corresponden. Pasarle una función específica como completeTodo mantiene cada componente enfocado en una sola responsabilidad [02:30].

En el span del ícono de completar agregamos el evento onClick, y dentro llamamos a props.onComplete. El componente hijo queda limpio: recibe una función y la ejecuta cuando corresponde.

Cómo crear la función completeTodo con setTodos y manipulación de arrays

En el componente padre creamos la función completeTodo que recibe un texto como identificador único. Como ya definimos que el texto del to-do es la key única en el render del array, lo usamos también para encontrar cuál modificar [05:45].

La lógica funciona así:

  • Crear una copia del estado actual usando el operador spread ([...todos]). Esto evita mutar el estado original, algo que React no permite.
  • Encontrar el índice del to-do que queremos modificar con el método findIndex, comparando todo.text con el texto recibido.
  • Acceder al objeto en esa posición del nuevo array y cambiar su propiedad completed a true.
  • Llamar a setTodos(newTodos) para actualizar el estado.

javascript const completeTodo = (text) => { const newTodos = [...todos]; const todoIndex = newTodos.findIndex( (todo) => todo.text === text ); newTodos[todoIndex].completed = true; setTodos(newTodos); };

Esta lógica más o menos enredosa la escribes una sola vez y la reutilizas para todos tus to-dos. El componente hijo no se entera de nada.

Por qué aparece el error too many re renders en React

Al pasar la función al componente hijo, hay una trampa que casi todo desarrollador cae al menos una vez. Si escribes onComplete={props.onComplete(todo.text)} con paréntesis, React ejecuta la función en cada render, lo que actualiza el estado, lo que dispara otro render, y así hasta que React se rinde [09:10].

El resultado es ese mensaje rojo desalentador: too many re-renders.

¿Qué significa el error too many re-renders en React? Significa que estás ejecutando una función que actualiza el estado durante el render, generando un bucle infinito. La solución es envolver la llamada en otra función que React solo ejecute cuando ocurra el evento.

La solución es la functionception: envolver la función en una arrow function.

javascript <TodoItem onComplete={() => completeTodo(todo.text)} />

Ahora React recibe una función sin ejecutar. Solo le pone los paréntesis cuando el usuario hace clic. La aplicación deja de crashear y los to-dos se completan al instante, actualizando también el contador en pantalla [11:20].

Cómo eliminar un to do en React con el método splice

Eliminar sigue exactamente el mismo patrón que completar, pero en vez de modificar una propiedad, removemos el elemento del array. Creamos una propiedad onDelete en el TodoItem y la asociamos al ícono de la X con un onClick.

La función deleteTodo reutiliza casi toda la lógica de completeTodo:

  • Recibe el texto del to-do a eliminar.
  • Crea una copia del array con spread.
  • Encuentra el índice con findIndex.
  • Usa el método splice para remover el elemento.
  • Actualiza el estado con setTodos.

javascript const deleteTodo = (text) => { const newTodos = [...todos]; const todoIndex = newTodos.findIndex( (todo) => todo.text === text ); newTodos.splice(todoIndex, 1); setTodos(newTodos); };

Qué hace el método splice y cómo funciona la analogía del pan tajado

El método splice recibe dos parámetros principales: la posición donde poner el cuchillo y cuántas tajadas cortar [13:50]. En nuestro caso, el cuchillo va en todoIndex y cortamos solo una tajada, es decir, un to-do.

¿Cuál es la diferencia entre splice y delete en JavaScript? splice modifica el array removiendo elementos y reorganizando los índices. delete deja un hueco con undefined en la posición. Para listas de to-dos, splice es más predecible.

Al recargar el navegador, ya puedes borrar to-dos completados y el contador refleja el cambio en tiempo real. La aplicación se siente viva.

Reto opcional para llevar tu to do counter al siguiente nivel

Un detalle que puedes mejorar es el mensaje del TodoCounter cuando todos los to-dos están completados. En vez de mostrar Has completado 5 de 5 TODOs, muestra algo más celebratorio como Felicitaciones, completaste todos los TODOs con un emoji.

Tienes todo lo necesario: el estado todos, el cálculo de completedTodos y un condicional. ¿Cómo lo resolverías tú? Cuéntamelo en los comentarios.