Saltar al contenido

Lección 10 de 13 · Lectura y práctica

Manejando multiples estados

Organizando el estado Multiples useState function Formulario() { const [nombre, setNombre] = useState(''); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [errors, setErrors] =.

Del concepto a la práctica

Taller de esta lección

Separar estados ayuda a que cada transición tenga un propósito claro. En un formulario de reserva, los campos pertenecen a los datos del visitante, mientras enviado describe la interfaz. Agrupar los campos relacionados reduce setters repetidos, pero no obliga a mezclar allí el estado visual.

Ejemplo resuelto

El bloque autónomo revisado se encuentra más abajo. Al cambiar nombre, correo se conserva porque se copia el objeto previo.

Pruébalo

  1. Define dos campos dentro de form.

  2. Actualiza por nombre de campo.

  3. Mantén enviado en un estado separado.

  4. Comprueba una transición de confirmación.

Comprueba tu resultado

Tras escribir “Ana” y “ana@ejemplo.test”, la cadena debe conservar ambos valores.

Error frecuente: reemplazar todo el objeto con { [name]: value }; corrígelo usando ...prev. No guardes nombreCompleto si puede calcularse a partir de campos existentes.

Formulario conectado y validación local

La versión autónoma siguiente sustituye el fragmento sin inputs ni handler de envío. Colócala en un archivo JSX y móntala desde App.

jsx
import {useState} from 'react';
export default function Reserva(){
  const [form,setForm]=useState({nombre:'',correo:''});
  const [enviado,setEnviado]=useState(false);
  const [error,setError]=useState('');
  function cambiar(e){
    const {name,value}=e.target;
    setForm(prev=>({...prev,[name]:value}));
    setEnviado(false);setError('');
  }
  function enviar(e){
    e.preventDefault();
    const valido=form.nombre.trim()!=='' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.correo.trim());
    setEnviado(valido);setError(valido?'':'Revisa nombre y correo');
  }
  return <form onSubmit={enviar}>
    <label>Nombre<input name="nombre" value={form.nombre} onChange={cambiar}/></label>
    <label>Correo<input name="correo" value={form.correo} onChange={cambiar}/></label>
    <button type="submit">Confirmar</button>
    <p>{enviado?'Confirmada':`${form.nombre}|${form.correo}`}</p>
    <p role="status">{error}</p>
  </form>;
}

Ana/ana@ejemplo.test conserva ambos campos y permite Confirmada; espacios/ana@ rechaza y conserva las entradas. El email usa una regla sencilla del laboratorio, no verifica un buzón real. Editar tras confirmar devuelve la vista a pendiente. No hay envío a servidor ni reserva persistida.

Nombre Ana y apellido Ruiz confluyen en un cálculo durante render que produce Ana Ruiz; se tacha un ciclo de efecto con fullName duplicado.
CursaloMapa de práctica
Calcula lo que ya tienes

Nombre y apellido son entradas de estado; el nombre completo se calcula durante render. Evitar otra copia de estado elimina la necesidad de sincronizar tres valores que representan la misma información.

Ver la infografía en tamaño completo ↗
La entrada Ana dispara onChange y setForm(nuevoForm); value={form.nombre} devuelve el estado al campo. Al enviar, un texto vacío tras trim conduce a Error y uno no vacío a Confirmada.
CursaloMapa de práctica
Entrada, estado y validación

El evento onChange crea nuevoForm, una copia del objeto con el nombre actualizado, y llama setForm(nuevoForm). La prop value refleja form.nombre; al enviar, trim detecta texto vacío y conserva el campo para corregirlo. Confirmada representa una validación local, no una respuesta de servidor.

Ver la infografía en tamaño completo ↗

Organizando el estado

Multiples useState

function Formulario() {
  const [nombre, setNombre] = useState('');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [errors, setErrors] = useState({});
  const [isSubmitting, setIsSubmitting] = useState(false);

  // Cada estado es independiente
  // Util cuando no estan relacionados
}

Estado agrupado

function Formulario() {
  // Agrupa estados relacionados
  const [form, setForm] = useState({
    nombre: '',
    email: '',
    password: ''
  });

  const [ui, setUi] = useState({
    isSubmitting: false,
    errors: {}
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm(prev => ({ ...prev, [name]: value }));
  };
}

Cuando separar vs agrupar?

  • Separar: Estados que cambian independientemente
  • Agrupar: Estados que siempre cambian juntos

Ejemplo practico: Filtros

function ProductList() {
  // Estados de filtro (relacionados)
  const [filters, setFilters] = useState({
    categoria: 'all',
    precioMin: 0,
    precioMax: 1000,
    ordenar: 'nombre'
  });

  // Estado de datos (independiente)
  const [productos, setProductos] = useState([]);

  // Estado de UI (independiente)
  const [isLoading, setIsLoading] = useState(false);

  const updateFilter = (key, value) => {
    setFilters(prev => ({ ...prev, [key]: value }));
  };

  return (
    <div>
      <select
        value={filters.categoria}
        onChange={(e) => updateFilter('categoria', e.target.value)}
      >
        <option value="all">Todas</option>
        <option value="tech">Tecnologia</option>
      </select>

      <input
        type="range"
        value={filters.precioMax}
        onChange={(e) => updateFilter('precioMax', e.target.value)}
      />
    </div>
  );
}

Levantando el estado (Lifting State)

// Cuando dos componentes necesitan compartir estado,
// muevelo al componente padre mas cercano

function App() {
  const [temperatura, setTemperatura] = useState(20);

  return (
    <div>
      <TermometroA temp={temperatura} onCambiar={setTemperatura} />
      <TermometroB temp={temperatura} onCambiar={setTemperatura} />
    </div>
  );
}

Sigue con React Fundamentals

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.