React useLayoutEffect — Measuring DOM Before Paint

Learn when to use useLayoutEffect instead of useEffect for DOM measurements. Covers tooltip positioning, scroll restoration, animation triggers, and preventing visual flicker.

Effect Hooks

Detailed Explanation

DOM Measurement with useLayoutEffect

useLayoutEffect runs synchronously after DOM mutations but before the browser paints. This makes it the right choice when you need to measure or modify the DOM before the user sees the update.

useEffect vs useLayoutEffect Timeline

Render -> DOM mutation -> useLayoutEffect -> Browser paint -> useEffect

Tooltip Positioning

function Tooltip({ targetRect, text }: {
  targetRect: DOMRect;
  text: string;
}) {
  const tooltipRef = useRef<HTMLDivElement>(null);
  const [position, setPosition] = useState({ x: 0, y: 0 });

  useLayoutEffect(() => {
    if (!tooltipRef.current) return;
    const tooltipRect = tooltipRef.current.getBoundingClientRect();
    setPosition({
      x: targetRect.left + (targetRect.width - tooltipRect.width) / 2,
      y: targetRect.top - tooltipRect.height - 8,
    });
  }, [targetRect]);

  return (
    <div ref={tooltipRef} style={{
      position: "fixed",
      left: position.x,
      top: position.y,
    }}>
      {text}
    </div>
  );
}

Why useEffect Would Flicker

With useEffect, the tooltip would first render at (0, 0), the browser would paint it there, and only then would the position be corrected -- causing a visible flicker. useLayoutEffect prevents this by updating the position before paint.

Scroll Restoration

useLayoutEffect(() => {
  const savedPosition = sessionStorage.getItem("scrollPos");
  if (savedPosition) {
    window.scrollTo(0, parseInt(savedPosition, 10));
  }
}, []);

Performance Warning

useLayoutEffect blocks the browser from painting. If your effect is slow, the user will see a frozen screen. Only use it when you genuinely need to prevent visual flicker. For most side effects, useEffect is the correct choice.

Use Case

Use useLayoutEffect for tooltip and popover positioning, preventing flicker when adjusting layout, scroll position restoration, measuring elements for animations, and any DOM operation that must complete before the user sees the frame.

Try It — React Hooks Reference

Open full tool