El hook useState permite que un componente React recuerde y actualice información sin recargar la página.
Cuando un usuario hace clic en un botón o escribe en un campo, la interfaz necesita cambiar. useState es la herramienta que hace posible ese cambio.
Qué es el estado en React
El estado es información que puede cambiar con el tiempo dentro de un componente.
A diferencia de las props, que vienen del componente padre y son de solo lectura, el estado es privado y lo controla el propio componente. Piensa en él como la memoria interna del componente.
Ejemplos de estado típico:
- El número de artículos en un carrito de Liverpool
- Si un menú está abierto o cerrado
- El texto que el usuario escribe en un formulario
- El precio total de una orden en Mercado Libre
Sintaxis de useState
useState se importa desde React y se llama dentro del cuerpo de un componente funcional.
Estructura básica:
import { useState } from 'react';
const [valor, setValor] = useState(valorInicial);
useState devuelve un arreglo con exactamente dos elementos:
| Elemento | Qué es | Ejemplo |
|---|---|---|
valor |
El estado actual | 0, false, "" |
setValor |
Función para actualizar el estado | setValor(1) |
valorInicial |
El valor con el que empieza | 0, true, [] |
Convención de nombres: Siempre nombra la función de actualización con el prefijo set. Si el estado se llama cantidad, la función es setCantidad.
Ejemplo 1 — Contador simple
Este es el ejemplo más directo para entender useState.
import { useState } from 'react';
function ContadorProductos() {
const [cantidad, setCantidad] = useState(0);
return (
<div>
<p>Productos en carrito: {cantidad}</p>
<button onClick={() => setCantidad(cantidad + 1)}>
Agregar
</button>
<button onClick={() => setCantidad(cantidad - 1)}>
Quitar
</button>
</div>
);
}
¿Qué pasa aquí?
cantidadempieza en0.- Cada clic en "Agregar" llama a
setCantidad(cantidad + 1). - React actualiza la pantalla automáticamente con el nuevo valor.
- El componente no se recarga: solo vuelve a renderizarse con el estado nuevo.
Resultado visible en pantalla:
Productos en carrito: 3
[Agregar] [Quitar]
Ejemplo 2 — Estado con booleano (mostrar/ocultar)
Un caso muy común en aplicaciones reales es mostrar u ocultar un elemento.
import { useState } from 'react';
function DetallePromocion() {
const [visible, setVisible] = useState(false);
return (
<div>
<button onClick={() => setVisible(!visible)}>
{visible ? 'Ocultar promoción' : 'Ver promoción'}
</button>
{visible && (
<p>¡20% de descuento en productos Bimbo esta semana!</p>
)}
</div>
);
}
Puntos clave:
!visibleinvierte el valor booleano cada vez que se hace clic.{visible && <p>...</p>}es renderizado condicional: solo muestra el párrafo cuandovisibleestrue.- El texto del botón también cambia según el estado actual.
Ejemplo 3 — Formulario con estado (más complejo)
Este ejemplo simula un campo de búsqueda como el de FEMSA o Liverpool.
import { useState } from 'react';
function BuscadorProducto() {
const [busqueda, setBusqueda] = useState('');
const [precioFiltro, setPrecioFiltro] = useState(0);
const handleBusqueda = (e) => {
setBusqueda(e.target.value);
};
const handlePrecio = (e) => {
setPrecioFiltro(Number(e.target.value));
};
return (
<div>
<input
type="text"
placeholder="Buscar producto..."
value={busqueda}
onChange={handleBusqueda}
/>
<input
type="number"
placeholder="Precio máximo"
value={precioFiltro}
onChange={handlePrecio}
/>
<p>Buscando: {busqueda}</p>
<p>Precio máximo: ${precioFiltro.toLocaleString('es-MX')}</p>
</div>
);
}
¿Qué es un input controlado?
Cuando escribes value={busqueda} y onChange={handleBusqueda}, el input es controlado. Esto significa que React es quien tiene el control del valor, no el navegador. Es la forma recomendada de manejar formularios en React.
Flujo de datos en un input controlado:
- El usuario escribe una letra.
- Se dispara el evento
onChange. setBusquedaactualiza el estado.- React vuelve a renderizar el componente con el nuevo valor.
- El input muestra el valor actualizado.
Reglas importantes de useState
Regla 1 — Solo se llama en el nivel superior del componente.
Nunca llames useState dentro de un if, un for o una función anidada.
// ❌ Incorrecto
if (condicion) {
const [valor, setValor] = useState(0);
}
// ✅ Correcto
const [valor, setValor] = useState(0);
if (condicion) {
setValor(10);
}
Regla 2 — Cada llamada a useState maneja una sola pieza de estado.
Si necesitas tres datos independientes, usa tres llamadas a useState.
const [nombre, setNombre] = useState('');
const [precio, setPrecio] = useState(0);
const [activo, setActivo] = useState(true);
Regla 3 — No mutés el estado directamente.
Siempre usa la función set. Modificar el estado directamente no dispara el re-render.
// ❌ Incorrecto — no causa re-render
cantidad = cantidad + 1;
// ✅ Correcto
setCantidad(cantidad + 1);
Errores comunes
Error 1 — Olvidar los corchetes en la desestructuración.
// ❌ Incorrecto
const resultado = useState(0);
// resultado es un arreglo, no el valor
// ✅ Correcto
const [contador, setContador] = useState(0);
Error 2 — Usar el valor anterior directamente en operaciones acumulativas.
Cuando el nuevo estado depende del estado anterior, usa la forma funcional.
// ❌ Puede fallar en actualizaciones rápidas
setCantidad(cantidad + 1);
// ✅ Forma segura con función
setCantidad(prev => prev + 1);
Esto importa cuando el usuario hace clic muy rápido o cuando hay múltiples actualizaciones seguidas.
Error 3 — Esperar que el estado se actualice de inmediato.
Llamar a setCantidad no cambia cantidad en la misma línea. React programa el re-render para después.
setCantidad(5);
console.log(cantidad); // Sigue mostrando el valor anterior
Error 4 — Poner objetos grandes en un solo useState innecesariamente.
Si dos datos no cambian juntos, es mejor separarlos en dos estados independientes. Esto hace el código más fácil de leer y depurar.
Referencia rápida de tipos de estado inicial
| Tipo de dato | Valor inicial típico | Ejemplo de uso |
|---|---|---|
| Número | 0 |
Contador, precio |
| Texto | '' |
Campo de búsqueda |
| Booleano | false |
Mostrar/ocultar |
| Arreglo | [] |
Lista de productos |
| Objeto | {} |
Datos de un formulario |
Cuándo usar useState y cuándo no
Usa useState cuando:
- El componente necesita recordar información entre renders.
- La información puede cambiar por una acción del usuario.
- Solo ese componente necesita esa información.
No uses useState cuando:
- El dato nunca cambia. Usa una constante normal.
- El dato viene del componente padre. Usa props.
- El dato lo necesitan muchos componentes distintos. En ese caso se usan soluciones más avanzadas como Context o Redux (temas fuera del alcance de esta lección).
Puntos clave
useStatedevuelve un arreglo de dos elementos: el valor actual y la función para actualizarlo.- Nunca modifiques el estado directamente. Siempre usa la función
setpara que React detecte el cambio y actualice la pantalla. - Los inputs controlados usan
valueyonChangejuntos para que React controle el contenido del campo. - Cada pieza de información independiente debe tener su propio
useState. - Cuando el nuevo estado depende del anterior, usa la forma funcional:
setValor(prev => prev + 1).