A tu propio ritmo

Explora nuestra extensa colección de cursos diseñados para ayudarte a dominar varios temas y habilidades. Ya seas un principiante o un aprendiz avanzado, aquí hay algo para todos.

Bootcamp

Aprende en vivo

Únete a nosotros en nuestros talleres gratuitos, webinars y otros eventos para aprender más sobre nuestros programas y comenzar tu camino para convertirte en desarrollador.

Próximos eventos en vivo

Catálogo de contenidos

Para los geeks autodidactas, este es nuestro extenso catálogo de contenido con todos los materiales y tutoriales que hemos desarrollado hasta el día de hoy.

Tiene sentido comenzar a aprender leyendo y viendo videos sobre los fundamentos y cómo funcionan las cosas.

Buscar en lecciones


← Regresar a lecciones

Componentes No Controlados en Formularios React

¿Qué son los Componentes No Controlados?
Implementando Componentes No Controlados
  • Ejemplo Básico

Aunque los componentes controlados son el enfoque recomendado para la mayoría de los escenarios de formularios en React, los componentes no controlados ofrecen una alternativa que puede ser más simple y eficiente en ciertas situaciones. Esta lección explora cuándo y cómo usar los componentes no controlados de manera efectiva.

¿Qué son los Componentes No Controlados?

Los componentes no controlados son elementos de formulario que mantienen su propio estado interno. En lugar de ser dirigidos por el estado de React, dependen del DOM para manejar los datos del formulario. Los valores se recuperan directamente del DOM cuando se necesitan, normalmente durante el envío del formulario.

La característica principal de los componentes no controlados es que React no "controla" los valores de los elementos del formulario durante el ciclo de vida del componente.

Cuándo Usar Componentes No Controlados

Los componentes no controlados pueden ser una buena elección cuando:

  1. Tienes formularios simples con pocas entradas
  2. Solo necesitas los datos del formulario al momento de envío
  3. Estás integrando con código o bibliotecas que no son de React
  4. Estás trabajando con entradas de archivo
  5. Necesitas optimizar el rendimiento con muchos campos de formulario

Implementando Componentes No Controlados

La herramienta principal para trabajar con componentes no controlados es el hook useRef de React (o createRef en componentes de clase).

Ejemplo Básico

1import React, { useRef } from "react"; 2 3function FormularioNoControlado() { 4 const refInputNombre = useRef(null); 5 const refInputEmail = useRef(null); 6 7 const manejarEnvio = (e) => { 8 e.preventDefault(); 9 const datosFormulario = { 10 nombre: refInputNombre.current.value, 11 email: refInputEmail.current.value 12 }; 13 console.log("Formulario enviado con datos:", datosFormulario); 14 // Procesar los datos del formulario 15 }; 16 17 return ( 18 <form onSubmit={manejarEnvio}> 19 <div> 20 <label htmlFor="nombre">Nombre:</label> 21 <input 22 type="text" 23 id="nombre" 24 ref={refInputNombre} 25 defaultValue="" // Valor inicial opcional 26 /> 27 </div> 28 29 <div> 30 <label htmlFor="email">Email:</label> 31 <input 32 type="email" 33 id="email" 34 ref={refInputEmail} 35 defaultValue="" 36 /> 37 </div> 38 39 <button type="submit">Enviar</button> 40 </form> 41 ); 42}

Puntos importantes a tener en cuenta:

  • Usamos ref para crear una referencia al elemento DOM
  • Usamos defaultValue en lugar de value para el valor inicial
  • Los datos del formulario se acceden a través de ref.current.value cuando se necesitan
  • No se requieren manejadores onChange

Trabajando con Diferentes Elementos de Formulario

Entradas de Texto

1function EntradaTextoNoControlada() { 2 const refInput = useRef(null); 3 4 return <input type="text" ref={refInput} defaultValue="Texto predeterminado" />; 5}

Casillas de Verificación

1function CasillaVerificacionNoControlada() { 2 const refCasilla = useRef(null); 3 4 const estaMarcada = () => { 5 return refCasilla.current.checked; 6 }; 7 8 return ( 9 <> 10 <label> 11 <input 12 type="checkbox" 13 ref={refCasilla} 14 defaultChecked={false} 15 /> 16 Acepto los términos 17 </label> 18 <button onClick={() => alert(estaMarcada())}> 19 Comprobar estado 20 </button> 21 </> 22 ); 23}

Nota: Para casillas de verificación, usa defaultChecked en lugar de defaultValue.

Listas Desplegables

1function SelectNoControlado() { 2 const refSelect = useRef(null); 3 4 const obtenerValorActual = () => { 5 return refSelect.current.value; 6 }; 7 8 return ( 9 <> 10 <select ref={refSelect} defaultValue="naranja"> 11 <option value="manzana">Manzana</option> 12 <option value="naranja">Naranja</option> 13 <option value="platano">Plátano</option> 14 </select> 15 <button onClick={() => alert(obtenerValorActual())}> 16 Obtener fruta seleccionada 17 </button> 18 </> 19 ); 20}

Entradas de Archivo

Las entradas de archivo son inherentemente no controladas en React, ya que su valor es de solo lectura:

1function EntradaArchivo() { 2 const refEntradaArchivo = useRef(null); 3 4 const manejarEnvio = (e) => { 5 e.preventDefault(); 6 const archivos = refEntradaArchivo.current.files; 7 // Procesar archivos 8 console.log(`Seleccionados ${archivos.length} archivos`); 9 }; 10 11 return ( 12 <form onSubmit={manejarEnvio}> 13 <input type="file" ref={refEntradaArchivo} multiple /> 14 <button type="submit">Subir</button> 15 </form> 16 ); 17}

Valores Predeterminados

Hay dos formas de especificar el valor inicial de un componente no controlado:

  1. Usando el atributo defaultValue (o defaultChecked para casillas de verificación y botones de radio)
  2. Usando el atributo HTML (aunque esto no es la manera de React)
1// Enfoque recomendado de React 2<input type="text" defaultValue="Valor inicial" ref={refInput} /> 3 4// Enfoque HTML (no recomendado en React) 5<input type="text" value="Valor inicial" ref={refInput} />

Ejemplo de Formulario Complejo

Aquí hay un ejemplo más completo que demuestra un formulario no controlado con varios tipos de entrada:

1import React, { useRef } from "react"; 2 3function FormularioRegistro() { 4 const refFormulario = useRef(null); 5 6 const manejarEnvio = (e) => { 7 e.preventDefault(); 8 const formulario = refFormulario.current; 9 10 const datosFormulario = { 11 nombre: formulario.nombre.value, 12 apellido: formulario.apellido.value, 13 email: formulario.email.value, 14 genero: formulario.genero.value, 15 intereses: Array.from(formulario.intereses) 16 .filter(casilla => casilla.checked) 17 .map(casilla => casilla.value), 18 pais: formulario.pais.value, 19 comentarios: formulario.comentarios.value 20 }; 21 22 console.log("Formulario enviado con:", datosFormulario); 23 // Procesar los datos 24 }; 25 26 return ( 27 <form ref={refFormulario} onSubmit={manejarEnvio}> 28 <div> 29 <label htmlFor="nombre">Nombre:</label> 30 <input type="text" id="nombre" name="nombre" defaultValue="" /> 31 </div> 32 33 <div> 34 <label htmlFor="apellido">Apellido:</label> 35 <input type="text" id="apellido" name="apellido" defaultValue="" /> 36 </div> 37 38 <div> 39 <label htmlFor="email">Email:</label> 40 <input type="email" id="email" name="email" defaultValue="" /> 41 </div> 42 43 <div> 44 <p>Género:</p> 45 <label> 46 <input type="radio" name="genero" value="masculino" defaultChecked /> 47 Masculino 48 </label> 49 <label> 50 <input type="radio" name="genero" value="femenino" /> 51 Femenino 52 </label> 53 <label> 54 <input type="radio" name="genero" value="otro" /> 55 Otro 56 </label> 57 </div> 58 59 <div> 60 <p>Intereses:</p> 61 <label> 62 <input type="checkbox" name="intereses" value="deportes" /> 63 Deportes 64 </label> 65 <label> 66 <input type="checkbox" name="intereses" value="musica" /> 67 Música 68 </label> 69 <label> 70 <input type="checkbox" name="intereses" value="lectura" /> 71 Lectura 72 </label> 73 </div> 74 75 <div> 76 <label htmlFor="pais">País:</label> 77 <select id="pais" name="pais" defaultValue=""> 78 <option value="" disabled>Selecciona un país</option> 79 <option value="usa">Estados Unidos</option> 80 <option value="canada">Canadá</option> 81 <option value="mexico">México</option> 82 <option value="otro">Otro</option> 83 </select> 84 </div> 85 86 <div> 87 <label htmlFor="comentarios">Comentarios:</label> 88 <textarea 89 id="comentarios" 90 name="comentarios" 91 defaultValue="" 92 rows="4" 93 /> 94 </div> 95 96 <button type="submit">Registrarse</button> 97 </form> 98 ); 99}

En este ejemplo, usamos una única referencia para todo el formulario y accedemos a los campos individuales por sus atributos de nombre.

Validación con Componentes No Controlados

Aunque los componentes no controlados no ofrecen validación en tiempo real tan fácilmente como los componentes controlados, aún puedes implementar validación:

1function FormularioNoControladoValidado() { 2 const refEmail = useRef(null); 3 const [errorEmail, setErrorEmail] = useState(""); 4 5 const validarEmail = () => { 6 const email = refEmail.current.value; 7 const esValido = /\S+@\S+\.\S+/.test(email); 8 9 if (!esValido) { 10 setErrorEmail("Por favor ingresa una dirección de email válida"); 11 return false; 12 } else { 13 setErrorEmail(""); 14 return true; 15 } 16 }; 17 18 const manejarEnvio = (e) => { 19 e.preventDefault(); 20 if (validarEmail()) { 21 // Lógica de envío del formulario 22 console.log("Formulario enviado con:", refEmail.current.value); 23 } 24 }; 25 26 return ( 27 <form onSubmit={manejarEnvio}> 28 <div> 29 <label htmlFor="email">Email:</label> 30 <input 31 type="email" 32 id="email" 33 ref={refEmail} 34 onBlur={validarEmail} 35 /> 36 {errorEmail && <p className="error">{errorEmail}</p>} 37 </div> 38 39 <button type="submit">Enviar</button> 40 </form> 41 ); 42}

En este patrón, validamos la entrada cuando pierde el foco (onBlur) o durante el envío del formulario.

Controlado vs. No Controlado: Comparación

Aquí hay una comparación rápida para ayudarte a decidir qué enfoque utilizar:

CaracterísticaControladoNo Controlado
Datos del formulario almacenados enEstado de ReactDOM
Acceso inmediato al valor de entradaNo (requiere acceso a ref)
Validación en tiempo realFácilMás complejo
Código requeridoMásMenos
Rendimiento con muchos camposPuede ser más lentoGeneralmente más rápido
Reinicio del formularioFácil (reiniciar estado)Requiere manipulación del DOM
Integración con código no ReactMás difícilMás fácil

Mejores Prácticas para Componentes No Controlados

  1. Usa componentes no controlados para formularios simples con requisitos mínimos de interacción
  2. Combina con atributos de validación HTML5 (required, pattern, etc.)
  3. Usa defaultValue/defaultChecked adecuadamente en lugar del atributo value de HTML
  4. Agrega atributos key a los elementos del formulario si necesitan ser reiniciados
  5. Implementa validación a nivel de formulario al enviar en lugar de validación a nivel de campo
  6. Considera la accesibilidad - los estados de error son más difíciles de comunicar automáticamente

Conclusión

Los componentes no controlados proporcionan una alternativa más simple y a veces más eficiente a los formularios controlados en React. Aunque ofrecen menos control sobre los datos del formulario durante el ciclo de vida del componente, requieren menos código y pueden ser más fáciles de implementar para formularios simples.

Para la mayoría de las aplicaciones React, los componentes controlados siguen siendo el enfoque recomendado debido a su previsibilidad e integración con el modelo de estado de React. Sin embargo, entender los componentes no controlados te da una herramienta adicional en tu kit de herramientas de React, especialmente útil para formularios simples, entradas de archivo o cuando se integra con código existente.