Formularios en React para Principiantes

 

Formularios en React para Principiantes

Los formularios en React manejan los datos de forma especial porque React controla la interfaz. Hay dos formas principales: controlados y no controlados.

1. Formularios Controlados (Recomendados)

En los formularios controlados, React maneja el estado de cada campo del formulario.

Ejemplo Básico:

jsx
import { useState } from 'react';

function FormularioSimple() {
  // Estado para almacenar el valor del input
  const [nombre, setNombre] = useState('');

  // Manejar el cambio en el input
  const manejarCambio = (e) => {
    setNombre(e.target.value);
  };

  // Manejar el envío del formulario
  const manejarEnvio = (e) => {
    e.preventDefault(); // Evita que la página se recargue
    alert(`Hola, ${nombre}!`);
  };

  return (
    <form onSubmit={manejarEnvio}>
      <label>
        Tu nombre:
        <input 
          type="text" 
          value={nombre} 
          onChange={manejarCambio}
        />
      </label>
      <button type="submit">Enviar</button>
      <p>Texto escrito: {nombre}</p>
    </form>
  );
}

2. Formulario con Múltiples Campos

jsx
import { useState } from 'react';

function FormularioRegistro() {
  // Estado para todos los campos
  const [formData, setFormData] = useState({
    nombre: '',
    email: '',
    password: '',
    aceptaTerminos: false
  });

  // Manejar cambios en cualquier campo
  const manejarCambio = (e) => {
    const { name, value, type, checked } = e.target;
    
    setFormData({
      ...formData, // Copiamos todos los valores anteriores
      [name]: type === 'checkbox' ? checked : value
    });
  };

  // Manejar envío
  const manejarEnvio = (e) => {
    e.preventDefault();
    console.log('Datos enviados:', formData);
    alert(`Registro exitoso para: ${formData.nombre}`);
  };

  return (
    <form onSubmit={manejarEnvio} style={{ maxWidth: '400px', margin: '20px auto' }}>
      <h2>Registro de Usuario</h2>
      
      <div style={{ marginBottom: '15px' }}>
        <label>Nombre completo: </label>
        <input
          type="text"
          name="nombre"
          value={formData.nombre}
          onChange={manejarCambio}
          style={{ width: '100%', padding: '8px' }}
        />
      </div>

      <div style={{ marginBottom: '15px' }}>
        <label>Email: </label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={manejarCambio}
          style={{ width: '100%', padding: '8px' }}
        />
      </div>

      <div style={{ marginBottom: '15px' }}>
        <label>Contraseña: </label>
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={manejarCambio}
          style={{ width: '100%', padding: '8px' }}
        />
      </div>

      <div style={{ marginBottom: '15px' }}>
        <label>
          <input
            type="checkbox"
            name="aceptaTerminos"
            checked={formData.aceptaTerminos}
            onChange={manejarCambio}
          />
          Acepto los términos y condiciones
        </label>
      </div>

      <button 
        type="submit"
        style={{ 
          padding: '10px 20px', 
          backgroundColor: '#4CAF50', 
          color: 'white', 
          border: 'none',
          cursor: 'pointer'
        }}
      >
        Registrarse
      </button>

      <div style={{ marginTop: '20px', padding: '10px', backgroundColor: '#f0f0f0' }}>
        <h3>Datos del formulario:</h3>
        <pre>{JSON.stringify(formData, null, 2)}</pre>
      </div>
    </form>
  );
}

3. Formulario con Validación

jsx
import { useState } from 'react';

function FormularioConValidacion() {
  const [formData, setFormData] = useState({
    email: '',
    password: ''
  });
  
  const [errores, setErrores] = useState({});

  const validarFormulario = () => {
    const nuevosErrores = {};

    if (!formData.email) {
      nuevosErrores.email = 'El email es requerido';
    } else if (!formData.email.includes('@')) {
      nuevosErrores.email = 'Email inválido';
    }

    if (!formData.password) {
      nuevosErrores.password = 'La contraseña es requerida';
    } else if (formData.password.length < 6) {
      nuevosErrores.password = 'La contraseña debe tener al menos 6 caracteres';
    }

    setErrores(nuevosErrores);
    return Object.keys(nuevosErrores).length === 0;
  };

  const manejarCambio = (e) => {
    const { name, value } = e.target;
    setFormData({
      ...formData,
      [name]: value
    });
    
    // Limpiar error cuando el usuario empieza a escribir
    if (errores[name]) {
      setErrores({
        ...errores,
        [name]: ''
      });
    }
  };

  const manejarEnvio = (e) => {
    e.preventDefault();
    
    if (validarFormulario()) {
      alert('Formulario enviado correctamente!');
      // Aquí normalmente enviarías los datos a un servidor
    }
  };

  return (
    <form onSubmit={manejarEnvio} style={{ maxWidth: '400px', margin: '20px auto' }}>
      <h2>Iniciar Sesión</h2>
      
      <div style={{ marginBottom: '15px' }}>
        <label>Email: </label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={manejarCambio}
          style={{ 
            width: '100%', 
            padding: '8px',
            border: errores.email ? '2px solid red' : '1px solid #ccc'
          }}
        />
        {errores.email && (
          <p style={{ color: 'red', fontSize: '14px' }}>{errores.email}</p>
        )}
      </div>

      <div style={{ marginBottom: '15px' }}>
        <label>Contraseña: </label>
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={manejarCambio}
          style={{ 
            width: '100%', 
            padding: '8px',
            border: errores.password ? '2px solid red' : '1px solid #ccc'
          }}
        />
        {errores.password && (
          <p style={{ color: 'red', fontSize: '14px' }}>{errores.password}</p>
        )}
      </div>

      <button 
        type="submit"
        style={{ 
          padding: '10px 20px', 
          backgroundColor: '#2196F3', 
          color: 'white', 
          border: 'none',
          cursor: 'pointer'
        }}
      >
        Iniciar Sesión
      </button>
    </form>
  );
}

4. Formulario con Select y Textarea

jsx
import { useState } from 'react';

function FormularioCompleto() {
  const [formulario, setFormulario] = useState({
    pais: 'es',
    comentarios: '',
    genero: 'femenino'
  });

  const manejarCambio = (e) => {
    const { name, value } = e.target;
    setFormulario({
      ...formulario,
      [name]: value
    });
  };

  const manejarEnvio = (e) => {
    e.preventDefault();
    console.log('Datos finales:', formulario);
    alert('Formulario enviado!');
  };

  return (
    <form onSubmit={manejarEnvio} style={{ maxWidth: '500px', margin: '20px auto' }}>
      <h2>Formulario Completo</h2>
      
      <div style={{ marginBottom: '15px' }}>
        <label>País: </label>
        <select 
          name="pais" 
          value={formulario.pais} 
          onChange={manejarCambio}
          style={{ width: '100%', padding: '8px' }}
        >
          <option value="es">España</option>
          <option value="mx">México</option>
          <option value="ar">Argentina</option>
          <option value="co">Colombia</option>
        </select>
      </div>

      <div style={{ marginBottom: '15px' }}>
        <label>Género: </label><br />
        <label>
          <input
            type="radio"
            name="genero"
            value="masculino"
            checked={formulario.genero === 'masculino'}
            onChange={manejarCambio}
          />
          Masculino
        </label>
        <br />
        <label>
          <input
            type="radio"
            name="genero"
            value="femenino"
            checked={formulario.genero === 'femenino'}
            onChange={manejarCambio}
          />
          Femenino
        </label>
        <br />
        <label>
          <input
            type="radio"
            name="genero"
            value="otro"
            checked={formulario.genero === 'otro'}
            onChange={manejarCambio}
          />
          Otro
        </label>
      </div>

      <div style={{ marginBottom: '15px' }}>
        <label>Comentarios: </label>
        <textarea
          name="comentarios"
          value={formulario.comentarios}
          onChange={manejarCambio}
          rows="4"
          style={{ width: '100%', padding: '8px' }}
          placeholder="Escribe tus comentarios aquí..."
        />
      </div>

      <button type="submit">Enviar</button>

      <div style={{ marginTop: '20px', padding: '10px', backgroundColor: '#f5f5f5' }}>
        <h4>Resumen:</h4>
        <p><strong>País:</strong> {formulario.pais}</p>
        <p><strong>Género:</strong> {formulario.genero}</p>
        <p><strong>Comentarios:</strong> {formulario.comentarios || '(ninguno)'}</p>
      </div>
    </form>
  );
}

5. Hook Personalizado para Formularios (Opcional avanzado)

jsx
// Hook personalizado reutilizable
function useFormulario(valoresIniciales) {
  const [valores, setValores] = useState(valoresIniciales);

  const manejarCambio = (e) => {
    const { name, value, type, checked } = e.target;
    setValores({
      ...valores,
      [name]: type === 'checkbox' ? checked : value
    });
  };

  const resetear = () => {
    setValores(valoresIniciales);
  };

  return [valores, manejarCambio, resetear];
}

// Componente que usa el hook personalizado
function FormularioConHookPersonalizado() {
  const [formData, manejarCambio, resetear] = useFormulario({
    usuario: '',
    edad: ''
  });

  const manejarEnvio = (e) => {
    e.preventDefault();
    console.log('Datos:', formData);
    alert(`Usuario: ${formData.usuario}, Edad: ${formData.edad}`);
  };

  return (
    <form onSubmit={manejarEnvio}>
      <input
        type="text"
        name="usuario"
        placeholder="Usuario"
        value={formData.usuario}
        onChange={manejarCambio}
      />
      <input
        type="number"
        name="edad"
        placeholder="Edad"
        value={formData.edad}
        onChange={manejarCambio}
      />
      <button type="submit">Enviar</button>
      <button type="button" onClick={resetear}>Limpiar</button>
    </form>
  );
}

Puntos Clave a Recordar:

  1. Formularios Controlados: Usa value y onChange para cada input

  2. Evento onSubmit: Maneja el envío del formulario

  3. e.preventDefault(): Siempre úsalo para evitar recarga de página

  4. Múltiples campos: Usa el atributo name para identificarlos

  5. Checkboxes/Radios: Usa checked en lugar de value

  6. Spread operator (...): Esencial para actualizar estado sin perder otros valores

Para Empezar:

Te recomiendo copiar estos ejemplos en tu proyecto React y:

  1. Primero prueba el FormularioSimple

  2. Luego experimenta con el FormularioRegistro

  3. Finalmente agrega validación con FormularioConValidacion

¡La práctica es clave! Comienza con formularios simples y ve agregando complejidad

Comentarios

Entradas más populares de este blog

Axios para Principiantes - Guía Paso a Paso

15-Tutorial: Crear Película en React con useState

Tutorial de React para Principiantes