Los componentes controlados son la forma recomendada por React para manejar entradas de formularios. En este enfoque, los datos del formulario son manejados por el estado de React, dándote más control, flexibilidad y poder al construir formularios interactivos.
Un componente controlado es un elemento de formulario cuyo valor es controlado por el estado de React. El componente no mantiene su propio estado interno; en su lugar, depende de las props pasadas desde su componente padre.
Este patrón sigue el principio de React de "única fuente de verdad", donde el estado del componente es la fuente de datos autoritativa.
Aquí hay un ejemplo básico de una entrada de texto controlada:
1import React, { useState } from "react"; 2 3function EntradaControlada() { 4 const [valor, setValor] = useState(""); 5 6 const manejarCambio = (evento) => { 7 setValor(evento.target.value); 8 }; 9 10 return ( 11 <div> 12 <input type="text" value={valor} onChange={manejarCambio} /> 13 <p>Valor actual: {valor}</p> 14 </div> 15 ); 16}
Observa estas características clave:
value
de la entrada está establecido a una variable de estadoonChange
actualiza el estado cuando el usuario escribePara formularios con múltiples campos, puedes usar un único objeto de estado:
1import React, { useState } from "react"; 2 3function FormularioDeRegistro() { 4 const [datosFormulario, setDatosFormulario] = useState({ 5 nombre: "", 6 apellido: "", 7 email: "", 8 contraseña: "" 9 }); 10 11 const manejarCambio = (evento) => { 12 const { name, value } = evento.target; 13 setDatosFormulario({ 14 ...datosFormulario, // Preservar los datos existentes del formulario 15 [name]: value // Actualizar solo el campo cambiado 16 }); 17 }; 18 19 const manejarEnvio = (evento) => { 20 evento.preventDefault(); 21 console.log("Formulario enviado:", datosFormulario); 22 // Procesar los datos del formulario (ej., llamada a API) 23 }; 24 25 return ( 26 <form onSubmit={manejarEnvio}> 27 <div> 28 <label htmlFor="nombre">Nombre:</label> 29 <input 30 type="text" 31 id="nombre" 32 name="nombre" 33 value={datosFormulario.nombre} 34 onChange={manejarCambio} 35 /> 36 </div> 37 38 <div> 39 <label htmlFor="apellido">Apellido:</label> 40 <input 41 type="text" 42 id="apellido" 43 name="apellido" 44 value={datosFormulario.apellido} 45 onChange={manejarCambio} 46 /> 47 </div> 48 49 <div> 50 <label htmlFor="email">Email:</label> 51 <input 52 type="email" 53 id="email" 54 name="email" 55 value={datosFormulario.email} 56 onChange={manejarCambio} 57 /> 58 </div> 59 60 <div> 61 <label htmlFor="contraseña">Contraseña:</label> 62 <input 63 type="password" 64 id="contraseña" 65 name="contraseña" 66 value={datosFormulario.contraseña} 67 onChange={manejarCambio} 68 /> 69 </div> 70 71 <button type="submit">Registrarse</button> 72 </form> 73 ); 74}
Los componentes controlados funcionan con todos los elementos de formulario HTML. Aquí hay algunos ejemplos comunes:
1function CasillaControlada() { 2 const [estaMarcada, setEstaMarcada] = useState(false); 3 4 return ( 5 <label> 6 <input 7 type="checkbox" 8 checked={estaMarcada} 9 onChange={(e) => setEstaMarcada(e.target.checked)} 10 /> 11 Estoy de acuerdo con los términos 12 </label> 13 ); 14}
1function GrupoDeRadioControlado() { 2 const [opcionSeleccionada, setOpcionSeleccionada] = useState("opcion1"); 3 4 const manejarCambioOpcion = (e) => { 5 setOpcionSeleccionada(e.target.value); 6 }; 7 8 return ( 9 <div> 10 <label> 11 <input 12 type="radio" 13 value="opcion1" 14 checked={opcionSeleccionada === "opcion1"} 15 onChange={manejarCambioOpcion} 16 /> 17 Opción 1 18 </label> 19 20 <label> 21 <input 22 type="radio" 23 value="opcion2" 24 checked={opcionSeleccionada === "opcion2"} 25 onChange={manejarCambioOpcion} 26 /> 27 Opción 2 28 </label> 29 </div> 30 ); 31}
1function SelectControlado() { 2 const [valorSeleccionado, setValorSeleccionado] = useState("manzana"); 3 4 return ( 5 <select 6 value={valorSeleccionado} 7 onChange={(e) => setValorSeleccionado(e.target.value)} 8 > 9 <option value="manzana">Manzana</option> 10 <option value="platano">Plátano</option> 11 <option value="naranja">Naranja</option> 12 </select> 13 ); 14}
Una ventaja importante de los componentes controlados es la capacidad de proporcionar retroalimentación inmediata a los usuarios:
1function EntradaValidada() { 2 const [email, setEmail] = useState(""); 3 const [esValido, setEsValido] = useState(true); 4 5 const validarEmail = (email) => { 6 const regexEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 7 return regexEmail.test(email); 8 }; 9 10 const manejarCambio = (e) => { 11 const nuevoEmail = e.target.value; 12 setEmail(nuevoEmail); 13 setEsValido(validarEmail(nuevoEmail) || nuevoEmail === ""); 14 }; 15 16 return ( 17 <div> 18 <input 19 type="email" 20 value={email} 21 onChange={manejarCambio} 22 style={{ borderColor: esValido ? "initial" : "red" }} 23 /> 24 {!esValido && <p style={{ color: "red" }}>Por favor ingresa una dirección de email válida</p>} 25 </div> 26 ); 27}
required
, min
, max
, etc.) para accesibilidadLos componentes controlados te dan un control preciso sobre el comportamiento del formulario en aplicaciones React. Al conectar elementos de formulario con el estado de React, puedes:
Aunque requieren más código inicial que los componentes no controlados, los beneficios de los componentes controlados superan ampliamente los costos para la mayoría de las aplicaciones, especialmente aquellas con formularios complejos o requisitos de validación.