Ambos ejecutan efectos, pero en momentos distintos respecto al repintado (paint) del navegador — y esa diferencia de tiempo es todo el punto.
Ambos ejecutan efectos, pero en momentos distintos respecto al repintado (paint) del navegador — y esa diferencia de tiempo es todo el punto.
useEffect se ejecuta después de que el navegador ha pintado. Es asíncrono y no bloqueante. Úsalo para casi todo (datos, suscripciones, registro de eventos).useLayoutEffect se ejecuta de forma síncrona después de que el DOM se ha modificado pero ANTES de que el navegador pinte. Úsalo cuando debas leer el layout y cambiar el DOM en el mismo frame para evitar un parpadeo visible.render → DOM updated → [useLayoutEffect runs] → browser paints → [useEffect runs]
Imagina medir un elemento y reposicionar un tooltip según su tamaño. Con useEffect, el usuario vería brevemente el tooltip en el lugar incorrecto y luego saltaría:
useLayoutEffect(() => {
const { height } = ref.current.getBoundingClientRect();
setTooltipTop(-height); // applied BEFORE paint → no visible jump
}, []);
Con useEffect, el mismo código se ejecuta después del paint → un parpadeo de un frame.
useLayoutEffect hace que la interfaz se sienta entrecortada, porque el navegador no puede pintar hasta que termine.Regla práctica: usa useEffect por defecto; recurre a useLayoutEffect solo para mediciones o mutaciones síncronas del DOM que, de otro modo, provocarían un parpadeo. Elegir el correcto evita tanto la pérdida de rendimiento de bloquear el paint como los molestos saltos visuales.