useLayoutEffect
useLayoutEffect fires synchronously after all DOM mutations but before the browser paints on screen.
Mental Model
"The Tape Measure: You measure the exact size of a room before the interior decorator paints the wall to avoid visual flickering."
Interactive Engine Simulation
Invariant:The stability of this sequence is what allows React to persist state across asynchronous render cycles.
Executable Code Snippet
1useLayoutEffect(() => {
2 // Runs SYNCHRONOUSLY after DOM mutations
3 // But BEFORE browser paint
4 const rect = ref.current.getBoundingClientRect();
5 setPos(rect.top);
6}, []);- 01.Component re-renders are triggered by state or prop changes.
- 02.Reconciliation algorithm diffs the Virtual DOM to minimize actual DOM updates.
- 03.Automatic batching optimizes multiple state updates into a single render cycle.
01. Blocking the Paint
`useLayoutEffect` is identical to `useEffect` in structure, but it runs **synchronously** before the browser has a chance to paint the screen. This means you can measure the size or position of DOM elements and update state before the user sees anything, preventing the "flicker" of an element jumping from its initial to final position.
Timing Comparison
- useEffect Asynchronous / Post-Paint
- useLayoutEffect Synchronous / Pre-Paint
02. Performance Warning
Because this hook is synchronous, heavy logic inside it will **block the user interface**. Your app will feel sluggish if you do expensive calculations here. 99% of the time, `useEffect` is the better choice. Only reach for `useLayoutEffect` if you see a visible UI glitch during DOM measurements.
Expert Rule
"If you're building a tooltip, a popover, or a complex drag-and-drop system, you'll need this hook to calculate position. For everything else (data fetching, logging, analytics), stick to 'useEffect'."