Resumen

Conectar un formulario con el estado global de una aplicación React es uno de los pasos más satisfactorios en el desarrollo frontend. Aquí se aborda cómo construir un componente de formulario desde cero, manejar eventos como submit y onChange, y comunicar los datos con un provider mediante useContext, todo dentro de una app de tareas pendientes.

¿Cómo hacer que un botón abra y cierre un modal con un solo clic?

Antes de construir el formulario, es necesario resolver un detalle de experiencia de usuario: el botón que abre el modal también debe poder cerrarlo. La solución está en cómo funcionan las funciones actualizadoras de estado en React.

Cuando usamos setState (o cualquier setter como setOpenModal), podemos enviarle directamente un valor (true o false), pero también podemos enviarle una función que recibe el estado anterior como parámetro, conocido como prevState [01:18].

  • Si el modal está cerrado, prevState es false; al negarlo con !, se convierte en true.
  • Si el modal está abierto, prevState es true; al negarlo, se convierte en false.

Esta técnica de negar el estado anterior (!prevState) es un patrón muy común para alternar valores booleanos. Además, para garantizar que el botón siempre se vea por encima del modal, basta con agregar z-index: 1 en el CSS del componente [00:40].

¿Cómo construir el componente TodoForm paso a paso?

El formulario vive en su propio componente llamado TodoForm, creado dentro de su carpeta con un archivo index.js [03:07]. Dentro se utiliza la etiqueta HTML <form> y se compone de tres elementos principales:

  • Un <label> que describe la acción.
  • Un <textarea> en lugar de un <input>, porque permite que el texto crezca verticalmente en vez de esconderse horizontalmente [04:00].
  • Dos botones: uno para cancelar y otro para añadir.

¿Por qué usar type submit en vez de onClick?

El botón de cancelar recibe type="button" y escucha el evento onClick. Pero el botón de añadir recibe type="submit" [05:38]. Esto significa que al hacer clic, se dispara el evento onSubmit del formulario, no un simple clic. Los formularios en HTML, por defecto, recargan la página al enviarse. Para evitarlo se usa el método preventDefault del evento [09:15]:

javascript const onSubmit = (event) => { event.preventDefault(); addTodo(newTodoValue); setOpenModal(false); };

preventDefault cancela el comportamiento por defecto del navegador y permite ejecutar la lógica personalizada sin recargar nada.

¿Cómo capturar lo que el usuario escribe con estado local?

Para saber qué texto ingresó el usuario, se crea un estado local con React.useState('') [08:00]. La variable newTodoValue almacena el contenido del textarea, y setNewTodoValue lo actualiza cada vez que el usuario escribe:

javascript const onChange = (event) => { setNewTodoValue(event.target.value); };

El textarea conecta su value al estado y su evento onChange a esta función. De esta forma, React siempre tiene control sobre el valor del campo, lo que se conoce como un componente controlado [08:40].

¿Cómo conectar el formulario al estado global con useContext?

El formulario necesita dos cosas del contexto: la función addTodo para agregar una nueva tarea y setOpenModal para cerrar el modal después de completar la acción [07:07].

Dentro del provider (TodoContext), la función addTodo recibe el texto y utiliza el método push para insertar un nuevo objeto en el array de tareas [07:28]:

javascript const addTodo = (text) => { const newTodos = [...todos]; newTodos.push({ text, completed: false }); saveTodos(newTodos); };

Cada tarea nueva se marca con completed: false por defecto. Luego se guarda tanto en el estado global como en localStorage, asegurando persistencia incluso al recargar la página [10:40].

Al presionar cancelar, se llama a setOpenModal(false) sin agregar nada. Al presionar añadir, primero se ejecuta addTodo con el texto y después se cierra el modal [11:30]. El resultado es una experiencia fluida: el usuario escribe, añade y ve su nueva tarea en la lista de inmediato.

El CSS final incluye estilos para el formulario, el label, el textarea con su placeholder y outline, y botones diferenciados para añadir y cancelar [13:00]. Con todo esto, la aplicación queda completa y funcional.

¿Ya personalizaste tu app de tareas? Comparte en los comentarios qué funcionalidades nuevas agregaste o cómo cambiaste el diseño.