effects

useLayoutEffect

Runs a side effect synchronously after DOM mutations but before the browser paints. Reach for it only when you need to measure the DOM and then mutate it in a way the user must never see mid-flight (e.g. tooltip positioning).

useLayoutEffect(setup, dependencies?)

Parameters & Behavior

Parameter Purpose
setup Synchronous effect body; may return a cleanup function
dependencies Same semantics as useEffect — re-runs when any value changes
blocking paint Delays paint until the effect returns — keep the work small
SSR behavior Emits a warning on the server; does not run there — guard with a useEffect fallback if needed

Examples

const ref = useRef(null);
useLayoutEffect(() => {
  const { height } = ref.current.getBoundingClientRect();
  setHeight(height);
}, []);

Measure an element before paint so a parent can lay itself out

useLayoutEffect(() => {
  tooltipRef.current.style.top = `${anchorRect.bottom + 8}px`;
}, [anchorRect]);

Position a tooltip synchronously to avoid a visible flicker

useLayoutEffect(() => {
  window.scrollTo(0, savedScrollY);
}, [route]);

Restore scroll position before the user sees the new page frame

const isoLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;

Isomorphic pattern — use useEffect on the server to silence the SSR warning

Gotcha

Blocks paint, so heavy work here freezes the UI — default to useEffect and only escalate when a visible flicker forces you to. Does not run on the server.

Related hooks

← All React hooks · Fix hydration mismatch