Manejo de formularios
Introducción
El manejo de formularios es una parte esencial en el desarrollo de aplicaciones web. En React, trabajamos con formularios de una manera declarativa, donde cada cambio en los campos de entrada (inputs) actualiza el estado del componente. Esto permite que el formulario esté siempre sincronizado con el estado.
1. Formulario Básico: Manejo de Estado con useState #
Ejemplo #
1import React, { useState } from "react"; 2 3function FormularioBasico() { 4 const [nombre, setNombre] = useState(""); 5 6 const manejarCambio = (e) => { 7 setNombre(e.target.value); 8 }; 9 10 const manejarEnvio = (e) => { 11 e.preventDefault(); 12 alert(`El nombre enviado es: ${nombre}`); 13 }; 14 15 return ( 16 <form onSubmit={manejarEnvio}> 17 <label> 18 Nombre: 19 <input type="text" value={nombre} onChange={manejarCambio} /> 20 </label> 21 <button type="submit">Enviar</button> 22 </form> 23 ); 24} 25 26export default FormularioBasico;
Explicación #
- Estado: Usamos
useStatepara guardar el valor del camponombre. - Control del Input: El valor del input (
value) está ligado al estado. - Manejo del Cambio: La función
manejarCambioactualiza el estado con el nuevo valor del input. - Manejo del Envío: La función
manejarEnvioevita el comportamiento por defecto del formulario y muestra el valor actual en una alerta.
2. Múltiples Campos con un Solo Estado #
Para formularios con varios campos, podemos usar un solo estado para almacenar todos los valores.
Ejemplo #
1import React, { useState } from "react"; 2 3function FormularioMultiple() { 4 const [formulario, setFormulario] = useState({ 5 nombre: "", 6 correo: "", 7 }); 8 9 const manejarCambio = (e) => { 10 const { name, value } = e.target; 11 setFormulario({ 12 ...formulario, 13 [name]: value, 14 }); 15 }; 16 17 const manejarEnvio = (e) => { 18 e.preventDefault(); 19 alert(`Datos enviados:\nNombre: ${formulario.nombre}\nCorreo: ${formulario.correo}`); 20 }; 21 22 return ( 23 <form onSubmit={manejarEnvio}> 24 <label> 25 Nombre: 26 <input type="text" name="nombre" value={formulario.nombre} onChange={manejarCambio} /> 27 </label> 28 <label> 29 Correo: 30 <input type="email" name="correo" value={formulario.correo} onChange={manejarCambio} /> 31 </label> 32 <button type="submit">Enviar</button> 33 </form> 34 ); 35} 36 37export default FormularioMultiple;
Explicación #
- Estado del Formulario: Usamos un objeto para almacenar los valores de cada campo.
nameen Inputs: Los inputs tienen un atributonameque indica qué campo están actualizando.- Manejo del Cambio: La función
manejarCambioactualiza el campo correspondiente en el estado.
3. Validación de Formularios #
Podemos agregar validaciones para asegurarnos de que los datos ingresados sean correctos.
Ejemplo #
1import React, { useState } from "react"; 2 3function FormularioValidacion() { 4 const [formulario, setFormulario] = useState({ 5 nombre: "", 6 correo: "", 7 }); 8 const [error, setError] = useState(""); 9 10 const manejarCambio = (e) => { 11 const { name, value } = e.target; 12 setFormulario({ 13 ...formulario, 14 [name]: value, 15 }); 16 setError(""); // Limpiar errores al escribir 17 }; 18 19 const manejarEnvio = (e) => { 20 e.preventDefault(); 21 if (!formulario.nombre || !formulario.correo) { 22 setError("Todos los campos son obligatorios"); 23 return; 24 } 25 if (!formulario.correo.includes("@")) { 26 setError("El correo debe ser válido"); 27 return; 28 } 29 alert("Formulario enviado correctamente"); 30 }; 31 32 return ( 33 <form onSubmit={manejarEnvio}> 34 <label> 35 Nombre: 36 <input type="text" name="nombre" value={formulario.nombre} onChange={manejarCambio} /> 37 </label> 38 <label> 39 Correo: 40 <input type="email" name="correo" value={formulario.correo} onChange={manejarCambio} /> 41 </label> 42 {error && <p style={{ color: "red" }}>{error}</p>} 43 <button type="submit">Enviar</button> 44 </form> 45 ); 46} 47 48export default FormularioValidacion;
Explicación #
- Estado de Errores: Creamos un estado separado para manejar mensajes de error.
- Validación en el Envío: Verificamos que los campos estén llenos y que el correo tenga un formato válido.
- Mensajes de Error: Mostramos un mensaje de error si la validación falla.
4. Usar un Custom Hook para Formularios #
Podemos encapsular la lógica de los formularios en un Custom Hook.
Hook useForm #
1import { useState } from "react"; 2 3function useForm(initialValues) { 4 const [values, setValues] = useState(initialValues); 5 6 const handleChange = (e) => { 7 const { name, value } = e.target; 8 setValues({ ...values, [name]: value }); 9 }; 10 11 const reset = () => setValues(initialValues); 12 13 return { values, handleChange, reset }; 14} 15 16export default useForm;
Usando el Hook #
1import React from "react"; 2import useForm from "./useForm"; 3 4function FormularioConCustomHook() { 5 const { values, handleChange, reset } = useForm({ 6 nombre: "", 7 correo: "", 8 }); 9 10 const manejarEnvio = (e) => { 11 e.preventDefault(); 12 alert(`Nombre: ${values.nombre}\nCorreo: ${values.correo}`); 13 reset(); 14 }; 15 16 return ( 17 <form onSubmit={manejarEnvio}> 18 <label> 19 Nombre: 20 <input type="text" name="nombre" value={values.nombre} onChange={handleChange} /> 21 </label> 22 <label> 23 Correo: 24 <input type="email" name="correo" value={values.correo} onChange={handleChange} /> 25 </label> 26 <button type="submit">Enviar</button> 27 </form> 28 ); 29} 30 31export default FormularioConCustomHook;
Ventajas del Custom Hook #
- Reutilización de Lógica: Puedes usar
useFormen cualquier formulario. - Código Limpio: Los componentes no necesitan manejar directamente el estado o las funciones de cambio.
5. Formularios Complejos con Campos Dinámicos #
Si necesitas agregar campos dinámicamente, React facilita este proceso.
Ejemplo #
1import React, { useState } from "react"; 2 3function FormularioDinamico() { 4 const [campos, setCampos] = useState([""]); 5 6 const agregarCampo = () => { 7 setCampos([...campos, ""]); 8 }; 9 10 const manejarCambio = (e, index) => { 11 const nuevosCampos = [...campos]; 12 nuevosCampos[index] = e.target.value; 13 setCampos(nuevosCampos); 14 }; 15 16 const manejarEnvio = (e) => { 17 e.preventDefault(); 18 alert(`Valores: ${campos.join(", ")}`); 19 }; 20 21 return ( 22 <form onSubmit={manejarEnvio}> 23 {campos.map((campo, index) => ( 24 <div key={index}> 25 <input 26 type="text" 27 value={campo} 28 onChange={(e) => manejarCambio(e, index)} 29 /> 30 </div> 31 ))} 32 <button type="button" onClick={agregarCampo}> 33 Agregar Campo 34 </button> 35 <button type="submit">Enviar</button> 36 </form> 37 ); 38} 39 40export default FormularioDinamico;
Explicación #
- Estado como Array: Usamos un array para almacenar los valores de cada campo.
- Agregar Campos: Agregamos un nuevo campo al array cuando el usuario hace clic en "Agregar Campo".
- Sincronización de Valores: Cada campo actualiza su posición en el array.
Resumen del tema
Conceptos clave #
- Componentes Controlados: el valor del input está regido exclusivamente por el estado de React (
value={state}) y se actualiza medianteonChange. - Formularios con Múltiples Campos: uso de objetos de estado y propiedades computadas en el handler:
setForm({ ...form, [e.target.name]: e.target.value }). - Prevención de Recarga:
e.preventDefault()en el handleronSubmitpara evitar la recarga predeterminada del navegador. - Validación de Formularios: comprobación síncrona o asíncrona de restricciones de datos antes de enviar la información al servidor.
- Campos Dinámicos: almacenamiento de listas de campos en arrays con adición o eliminación por índice inmutable.
Qué debes recordar #
En React los formularios se gestionan mediante componentes controlados donde el estado actúa como la única fuente de la verdad sincronizada con los inputs.