React Hooks Explicados: useState y useEffect para Principiantes
Guía completa de React Hooks para principiantes. Aprende useState y useEffect con ejemplos prácticos, casos de uso y mejores prácticas.
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# React Hooks Explicados: useState y useEffect para Principiantes
Los Hooks revolucionaron React en 2019, permitiendo usar estado y efectos en componentes funcionales. Esta guía explica los 2 Hooks más importantes: useState y useEffect.
---
¿Qué Son los Hooks?
Hooks son funciones especiales que te permiten "enganchar" características de React en componentes funcionales.Antes de Hooks (Clases)
class Contador extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return (
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Clicks: {this.state.count}
</button>
);
}
}
Con Hooks (Funciones)
function Contador() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicks: {count}
</button>
);
}
Mucho más simple! ✨
---
Hook #1: useState
useState te permite añadir estado a componentes funcionales.
Sintaxis Básica
const [variable, setVariable] = useState(valorInicial);
- variable: El valor actual del estado
- setVariable: Función para actualizar el estado
- valorInicial: Valor al montar el componente
Ejemplo Simple
import { useState } from 'react';
function ContadorSimple() {
const [count, setCount] = useState(0);
return (
<div>
<p>Has hecho clic {count} veces</p>
<button onClick={() => setCount(count + 1)}>
Incrementar
</button>
</div>
);
}
Tipos de Datos en useState
String
const [nombre, setNombre] = useState('');
<input
value={nombre}
onChange={(e) => setNombre(e.target.value)}
/>
Boolean
const [mostrar, setMostrar] = useState(false);
<button onClick={() => setMostrar(!mostrar)}>
Toggle
</button>
{mostrar && <p>Contenido visible</p>}
Array
const [items, setItems] = useState([]);
const agregarItem = () => {
setItems([...items, 'Nuevo item']);
};
Object
const [usuario, setUsuario] = useState({
nombre: '',
email: ''
});
const actualizar = () => {
setUsuario({ ...usuario, nombre: 'Ana' });
};
Múltiples Estados
function Formulario() {
const [nombre, setNombre] = useState('');
const [email, setEmail] = useState('');
const [edad, setEdad] = useState(0);
return (
<form>
<input
value={nombre}
onChange={(e) => setNombre(e.target.value)}
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="number"
value={edad}
onChange={(e) => setEdad(Number(e.target.value))}
/>
</form>
);
}
Actualizar Estado Basado en Anterior
❌ Incorrecto:
setCount(count + 1);
setCount(count + 1); // No funciona como esperas
✅ Correcto:
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1); // Funciona bien
---
Hook #2: useEffect
useEffect te permite realizar efectos secundarios en componentes.
¿Qué Son Efectos Secundarios?
- Fetch de datos (API calls)
- Suscripciones
- Manipular DOM directamente
- Timers (setTimeout, setInterval)
- Logging
Sintaxis Básica
useEffect(() => {
// Código del efecto
return () => {
// Cleanup (opcional)
};
}, [dependencias]);
Ejemplo: Actualizar Título
import { useState, useEffect } from 'react';
function Contador() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = Clicks: ${count};
}, [count]); // Se ejecuta cuando count cambia
return (
<button onClick={() => setCount(count + 1)}>
Clicks: {count}
</button>
);
}
Array de Dependencias
Sin dependencias - Cada render
useEffect(() => {
console.log('Se ejecuta en CADA render');
});
Array vacío - Solo al montar
useEffect(() => {
console.log('Solo al montar el componente');
}, []); // ← Array vacío
Con dependencias - Cuando cambian
useEffect(() => {
console.log('count cambió');
}, [count]); // Se ejecuta cuando count cambia
---
Casos de Uso Comunes
1. Fetch de API
function Usuarios() {
const [usuarios, setUsuarios] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('https://api.example.com/usuarios')
.then(res => res.json())
.then(data => {
setUsuarios(data);
setLoading(false);
});
}, []); // Solo al montar
if (loading) return <p>Cargando...</p>;
return (
<ul>
{usuarios.map(user => (
<li key={user.id}>{user.nombre}</li>
))}
</ul>
);
}
2. Temporizador
function Reloj() {
const [segundos, setSegundos] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSegundos(s => s + 1);
}, 1000);
// Cleanup: limpiar al desmontar
return () => clearInterval(interval);
}, []);
return <p>Segundos: {segundos}</p>;
}
3. Event Listeners
function TamanoPantalla() {
const [ancho, setAncho] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => {
setAncho(window.innerWidth);
};
window.addEventListener('resize', handleResize);
// Cleanup
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return <p>Ancho: {ancho}px</p>;
}
4. LocalStorage
function ContadorPersistente() {
const [count, setCount] = useState(() => {
const guardado = localStorage.getItem('count');
return guardado ? parseInt(guardado) : 0;
});
useEffect(() => {
localStorage.setItem('count', count);
}, [count]);
return (
<button onClick={() => setCount(count + 1)}>
Clicks: {count}
</button>
);
}
---
Proyecto Completo: Lista de Tareas
import { useState, useEffect } from 'react';
function ListaTareas() {
const [tareas, setTareas] = useState(() => {
const guardadas = localStorage.getItem('tareas');
return guardadas ? JSON.parse(guardadas) : [];
});
const [input, setInput] = useState('');
// Guardar en localStorage cuando cambian las tareas
useEffect(() => {
localStorage.setItem('tareas', JSON.stringify(tareas));
}, [tareas]);
const agregarTarea = () => {
if (input.trim()) {
setTareas([...tareas, {
id: Date.now(),
texto: input,
completada: false
}]);
setInput('');
}
};
const toggleTarea = (id) => {
setTareas(tareas.map(tarea =>
tarea.id === id
? { ...tarea, completada: !tarea.completada }
: tarea
));
};
const eliminarTarea = (id) => {
setTareas(tareas.filter(tarea => tarea.id !== id));
};
return (
<div>
<h1>Mis Tareas</h1>
<div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && agregarTarea()}
placeholder="Nueva tarea..."
/>
<button onClick={agregarTarea}>Agregar</button>
</div>
<ul>
{tareas.map(tarea => (
<li key={tarea.id}>
<input
type="checkbox"
checked={tarea.completada}
onChange={() => toggleTarea(tarea.id)}
/>
<span style={{
textDecoration: tarea.completada ? 'line-through' : 'none'
}}>
{tarea.texto}
</span>
<button onClick={() => eliminarTarea(tarea.id)}>
Eliminar
</button>
</li>
))}
</ul>
<p>Total: {tareas.length} | Completadas: {tareas.filter(t => t.completada).length}</p>
</div>
);
}
---
Errores Comunes
1. Olvidar Dependencias
❌ Problema:
useEffect(() => {
console.log(count);
}, []); // count no está en dependencias
✅ Solución:
useEffect(() => {
console.log(count);
}, [count]);
2. Loops Infinitos
❌ Problema:
useEffect(() => {
setCount(count + 1); // ¡Causa loop infinito!
}, [count]);
✅ Solución:
// Usa condición o quita dependencia
useEffect(() => {
if (count < 10) {
setCount(count + 1);
}
}, [count]);
3. No Limpiar Efectos
❌ Problema:
useEffect(() => {
const timer = setInterval(() => {...}, 1000);
// No limpia el timer
});
✅ Solución:
useEffect(() => {
const timer = setInterval(() => {...}, 1000);
return () => clearInterval(timer); // Cleanup
}, []);
---
Reglas de los Hooks
✅ DO's
❌ DON'Ts
❌ No hagas esto:
if (condicion) {
const [count, setCount] = useState(0); // ❌ Error
}
✅ Haz esto:
const [count, setCount] = useState(0);
if (condicion) {
// Usa count aquí
}
---
Custom Hooks
Crea tus propios Hooks reutilizables:
// Hook personalizado
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
});
}, [url]);
return { data, loading };
}
// Usar el hook
function App() {
const { data, loading } = useFetch('https://api.example.com/data');
if (loading) return <p>Cargando...</p>;
return <div>{JSON.stringify(data)}</div>;
}
---
Otros Hooks Útiles
useContext
const valor = useContext(MiContexto);
useRef
const inputRef = useRef(null);
<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>
Focus Input
</button>
useMemo
const resultado = useMemo(() =>{
return calcularValorCostoso(dep);
}, [dep]);
---
Conclusión
Los Hooks useState y useEffect son fundamentales en React moderno:
✅ useState - Gestiona estado del componente
✅ useEffect - Maneja efectos secundarios
✅ Más simples que componentes de clase
✅ Reutilizables con custom hooks
Próximo paso: Practica creando una app de tareas con estos Hooks.---
Recursos Relacionados
---
Última actualización: 15 de febrero de 2026Artículos Relacionados
JavaScript y JSON: Guía Completa de JSON.parse() y JSON.stringify()
Domina el trabajo con JSON en JavaScript. Aprende JSON.parse(), JSON.stringify() y mejores prácticas para aplicaciones web modernas.
¿Qué es React y Por Qué Deberías Aprenderlo en 2026?
Descubre qué es React, cómo funciona y por qué es la biblioteca de JavaScript más popular para desarrollo web. Guía completa para principiantes con ejemplos prácticos.
Next.js vs React: ¿Cuál Deberías Elegir en 2026?
Comparativa completa entre Next.js y React. Descubre las diferencias clave, ventajas de cada uno y cuándo usar Next.js o React para tu proyecto web.