DevPath · Aprende a programar ESPTEN

useEffect, useRef y efectos

useEffect: efectos secundarios

Más allá del render

Un componente, en esencia, calcula JSX a partir de props y estado. Pero a veces necesitas hacer algo que no es calcular la interfaz: suscribirte a un evento del navegador, arrancar un temporizador, cambiar el título de la pestaña, hablar con una API... A esto se le llama efecto secundario (side effect), porque afecta a algo de fuera del componente.

Estas acciones no deben hacerse durante el render (el render debe ser puro y puede ejecutarse varias veces). Para eso existe el hook useEffect: dice "ejecuta este código después de pintar, para sincronizar con algo externo".

function Titulo() {
  const [n, setN] = useState(0);

  useEffect(() => {
    document.title = "Pulsado " + n + " veces";
  });

  return <button onClick={() => setN(n + 1)}>Pulsar</button>;
}

useEffect recibe una función (el efecto) que React ejecuta tras renderizar.

El array de dependencias

El segundo argumento de useEffect es un array que controla cuándo se vuelve a ejecutar el efecto:

// 1) Sin array: en CADA render
useEffect(() => { /* ... */ });

// 2) Array vacío []: solo UNA vez, al MONTAR el componente
useEffect(() => { /* ... */ }, []);

// 3) Con dependencias: al montar y cada vez que CAMBIE alguna de ellas
useEffect(() => { /* ... */ }, [userId]);

Regla de oro: incluye en las dependencias todo valor reactivo (props, estado) que uses dentro del efecto. Si lo omites, trabajarás con datos viejos.

La función de limpieza

Muchas suscripciones hay que deshacerlas: un temporizador hay que pararlo, un listener hay que quitarlo. Para eso, el efecto puede devolver una función de limpieza. React la ejecuta antes de volver a lanzar el efecto y al desmontar el componente.

function Reloj() {
  const [seg, setSeg] = useState(0);

  useEffect(() => {
    const id = setInterval(() => setSeg((s) => s + 1), 1000);
    return () => clearInterval(id); // limpieza: para el intervalo
  }, []);

  return <p>{seg} s</p>;
}

Sin esa limpieza, el intervalo seguiría vivo tras desmontar el componente: una fuga de recursos (y posibles errores). La limpieza evita suscripciones duplicadas y deja el sistema como estaba.

Mientras renderizas piensa: "¿qué hay que conectar?" (el efecto) y "¿qué hay que desconectar?" (la limpieza).

Pon esto en práctica

DevPath es un curso práctico: aquí lees la teoría; en la app la pones en práctica con ejercicios que se ejecutan de verdad, sin conexión.

Empezar gratis en la app →
Cargar datos con useEffect →