Saltar al contenido
Curso de React
Todos los cursos Ir al ejercicio →

Efectos con useEffect

  • ⏱ 55 minutos
  • 📶 Nivel: principiante
  • 🧩 Incluye ejercicio

💡 🎯 Al terminar esta lección podrás…

  • Sincronizar un componente con el exterior con useEffect.
  • Controlar cuándo se ejecuta un efecto con dependencias.
  • Limpiar temporizadores y oyentes.
  • Distinguir cuándo no hace falta un efecto.

1.Efectos: cuando React necesita hablar con el exterior

Dibujar un componente debe ser algo puro y predecible: los mismos datos producen la misma pantalla. Pero a veces necesitas hacer cosas fuera de React: cambiar el título de la pestaña, guardar en localStorage, escuchar el teclado, iniciar un temporizador, pedir datos a internet. Esas acciones se llaman efectos secundarios y su lugar es useEffect.

Dentro del dibujo (render)En un efecto (useEffect)
Calcular el JSX a partir de props y estadoCambiar document.title
Transformar datos (map, filter)Leer/escribir localStorage
Decidir qué mostrarCrear temporizadores y suscripciones
No debe tener efectos secundariosPedir datos a un servidor
⚛️ Tu primer efecto: el título de la pestaña
Consola

📌 Nota · Cuándo se ejecuta

React ejecuta el efecto después de dibujar el componente en pantalla. En el ejemplo, cada vez que cambia cuenta, el componente se vuelve a dibujar y el efecto corre otra vez (míralo en la consola).

2.El arreglo de dependencias

Ejecutar el efecto en cada dibujo casi nunca es lo que quieres. El segundo argumento de useEffect es un arreglo de dependencias que controla cuándo se vuelve a ejecutar:

EscribesEl efecto se ejecuta…Úsalo para
useEffect(fn)Después de cada dibujoCasi nunca
useEffect(fn, [])Una sola vez, al aparecer el componenteConfiguración inicial, suscripciones
useEffect(fn, [a, b])Al aparecer y cuando cambie a o bSincronizar con unos datos concretos
⚛️ Qué dispara cada efecto
Consola

⚠️ Importante · Declara todo lo que usas

Incluye en el arreglo todas las variables de props o estado que el efecto lee. Si te falta alguna, el efecto trabajará con valores viejos. Los linters de React (eslint-plugin-react-hooks) te avisan de ello; hazles caso.

3.La función de limpieza

Algunos efectos dejan algo funcionando: un temporizador, un oyente de eventos. Si no los detienes, se acumulan. Para eso el efecto puede devolver una función de limpieza, que React ejecuta antes de repetir el efecto y cuando el componente desaparece.

⚛️ Un temporizador que se limpia solo
Consola
  1. Al aparecer Reloj, el efecto inicia el intervalo.
  2. Cada segundo setSegundos(s => s + 1) actualiza el estado.
  3. Al ocultarlo, React ejecuta la limpieza y detiene el intervalo (míralo en la consola).

💡 Consejo · Oyentes de eventos

El patrón es idéntico para window.addEventListener("resize", fn): añade el oyente en el efecto y quítalo con removeEventListener en la limpieza. Así nunca duplicas oyentes.

4.Ejemplo útil: guardar en localStorage

Un uso muy habitual es persistir datos para que sobrevivan a recargar la página. Se hace en dos pasos: leer al empezar (con un valor inicial calculado una sola vez) y guardar con un efecto cada vez que cambia el dato.

⚛️ Una nota que se guarda sola
Consola

📌 Nota · El estado inicial perezoso

useState(() => …) con una función hace que el cálculo (aquí, leer localStorage) se ejecute solo la primera vez. Si escribieras useState(localStorage.getItem("nota")), se leería en cada dibujo aunque el resultado se ignore.

📌 Nota · Sobre estos editores

Dentro de las lecciones el localStorage es una copia temporal de la página, así que la nota se pierde al pulsar Ejecutar o recargar. En un proyecto real en tu navegador sí persiste.

5.Cuándo NO usar un efecto

useEffect es un recurso para sincronizar con el exterior, no para todo. El error más común de quien empieza es usarlo para calcular datos que ya se pueden deducir:

❌ Efecto innecesario
const [precio, setPrecio] = useState(10);
const [cantidad, setCantidad] = useState(2);
const [total, setTotal] = useState(0);

useEffect(() => {
  setTotal(precio * cantidad);   // dibuja dos veces cada cambio
}, [precio, cantidad]);
✅ Calcúlalo mientras dibujas
const [precio, setPrecio] = useState(10);
const [cantidad, setCantidad] = useState(2);
const total = precio * cantidad;   // valor derivado
SituaciónQué usar
Dato que sale de otros datos (total, filtrado)Una variable normal calculada al dibujar
Respuesta a un clic o un envíoEl manejador de eventos (onClick, onSubmit)
Reiniciar estado cuando cambia una propUna key distinta en el componente
Sincronizar con algo externo (título, red, temporizador)useEffect

💡 Consejo · Pregúntate

«¿Esto ocurre porque algo se mostró o porque el usuario hizo algo?». Lo segundo va en un manejador de eventos. Solo lo primero necesita un efecto.

6.Un detalle: el modo estricto en desarrollo

En los proyectos creados con Vite, main.jsx envuelve la aplicación en <StrictMode>. En desarrollo, React ejecuta cada efecto dos veces (monta, limpia y vuelve a montar) para ayudarte a descubrir efectos sin limpieza. En producción solo se ejecuta una vez.

Si ves un mensaje duplicado en la consola de tu proyecto, no es un error: es React comprobando que tu limpieza funciona. Si tu efecto está bien escrito, no notarás ninguna diferencia.

7.Errores frecuentes

📒 Apuntes para llevar

  • useEffect sirve para sincronizar con el exterior: título, localStorage, temporizadores, red.
  • Se ejecuta después de dibujar.
  • Dependencias: ninguna (cada dibujo), [] (una vez) o [a, b] (cuando cambian).
  • Incluye en el arreglo todo lo que el efecto lee.
  • Devuelve una función de limpieza para detener temporizadores y oyentes.
  • useState(() => …) calcula el valor inicial una sola vez.
  • No uses efectos para datos derivados ni para responder a clics.
  • En desarrollo, StrictMode ejecuta los efectos dos veces para detectar limpiezas incorrectas.

8.Glosario

TérminoSignificado
Efecto secundarioAcción que afecta algo fuera del componente: red, título, almacenamiento, temporizadores.
useEffectHook que ejecuta código después de dibujar y lo sincroniza con unas dependencias.
DependenciasValores que, al cambiar, vuelven a ejecutar el efecto.
LimpiezaFunción que devuelve el efecto para deshacer lo que hizo.
Estado inicial perezosoPasar una función a useState para calcular el valor inicial solo una vez.
StrictModeModo de desarrollo que repite renders y efectos para destapar errores.

🧠 Comprueba lo aprendido

Elige una respuesta en cada pregunta. Verás al instante si acertaste y por qué.

¿Cuándo corre useEffect(fn, [])?

¿Para qué sirve la función que devuelve un efecto?

Quieres mostrar precio * cantidad. ¿Qué es lo correcto?

¿Qué ocurre con useEffect(() => setN(n + 1)) sin dependencias?

¿Qué hace useState(() => localStorage.getItem("x"))?

Tu progreso se guarda en este navegador y se refleja en el índice del curso.

💡 🚀 ¡Ahora te toca!

La práctica fija lo aprendido. Pasa al ejercicio de esta lección.

Ir al ejercicio