4 min read
0%

useLayoutEffect vs useEffect

Back to Blog
useLayoutEffect vs useEffect

useLayoutEffect vs useEffect

Both hooks run after render, but at different times. The timing difference matters for DOM measurements and avoiding visual flicker.

Timing

Render → DOM mutations (commit) → useLayoutEffect → Browser paint → useEffect
  • useLayoutEffect fires synchronously after DOM mutations, before the browser paints
  • useEffect fires asynchronously after the browser paints

useLayoutEffect for Measurements

function Tooltip({ targetRef, content }) {
  const tooltipRef = useRef(null);
  const [position, setPosition] = useState({ top: 0, left: 0 });

  useLayoutEffect(() => {
    const targetRect = targetRef.current.getBoundingClientRect();
    const tooltipRect = tooltipRef.current.getBoundingClientRect();
    setPosition({
      top: targetRect.bottom + 8,
      left: targetRect.left - tooltipRect.width / 2,
    });
  }, []);

  return (
    <div ref={tooltipRef} style={position}>
      {content}
    </div>
  );
}

With useEffect, the tooltip briefly renders at {top: 0, left: 0} before snapping to position — a visible flash. With useLayoutEffect, the position is computed and applied before paint.

When to Use Which

useEffect (default for almost everything):

  • Data fetching
  • Subscriptions
  • Analytics, logging
  • Any side effect that doesn’t need to block paint

useLayoutEffect (only when needed):

  • Reading DOM layout (getBoundingClientRect, scrollHeight, offsetWidth)
  • Synchronously re-positioning or resizing elements based on measurements
  • Preventing visual flicker from layout calculations

SSR Warning

useLayoutEffect doesn’t run during SSR. React warns:

Warning: useLayoutEffect does nothing on the server

Suppress safely with an isomorphic hook:

const useIsomorphicLayoutEffect =
  typeof window === 'undefined' ? useEffect : useLayoutEffect;

Don’t Overuse

useLayoutEffect blocks the browser from painting until it completes. Heavy work inside it causes jank. Keep it focused on DOM reads and minimal, targeted writes.


Canvas is not supported in your browser