Skip to main content

When should you use useLayoutEffect?

Short version: why it exists

useLayoutEffect() is a version of useEffect() that runs right after React has updated the DOM, but before the browser paints the changes on the screen.

That is, it gives you the ability to:

measure or change the DOM before the user sees it.


Use useLayoutEffect when you need to:

1. Measure the DOM before it paints

If you want to get exact dimensions or the position of an element (for example, to calculate the position of a popup, a tooltip, a caret, etc.), use useLayoutEffect so the browser doesn't get a chance to paint the "old" state.

javascript
function Tooltip({ text }) { const ref = useRef(null); useLayoutEffect(() => { const { width, height } = ref.current.getBoundingClientRect(); console.log("Element size before display:", width, height); }, []); return <div ref={ref}>{text}</div>; }

Why not useEffect: in useEffect the measurements happen after the paint, and the data can already be stale (or cause a "jump").


2. Synchronize visual state with the DOM

If you manually change the DOM (for example, positioning, scrolling, or applying an animation), and you don't want the user to see an intermediate state, do it in useLayoutEffect.

javascript
useLayoutEffect(() => { elementRef.current.scrollTop = elementRef.current.scrollHeight; }, [messages]);

This way the scroll happens before the content is displayed, and there is no visual "jump".


3. Prevent a "flicker" or "jump" in the interface

Sometimes, when a component loads, you change sizes, positions, classes, etc. If you do this via useEffect, React shows the old UI first, then "rebuilds" it, and the user sees a "flash".

Using useLayoutEffect solves this:

javascript
useLayoutEffect(() => { ref.current.style.transform = "translateY(50px)"; }, []);

The effect is applied before paint, and the user sees the final look right away.


4. Animation synchronization

If you work with animation libraries (Framer Motion, GSAP, Anime.js, etc.) and need an animation to start at the exact moment before the paint, useLayoutEffect gives you that precision.

javascript
useLayoutEffect(() => { gsap.from(ref.current, { opacity: 0, y: -20, duration: 0.3 }); }, []);

5. When logic depends on an immediate DOM update

Sometimes you change state and must read up-to-date sizes/positions right after. useEffect would be too late, because the browser has already "shown" the old state.

Example: computing a block's height when state changes:

javascript
useLayoutEffect(() => { const h = ref.current.offsetHeight; console.log("Current height:", h); }, [isOpen]);

When you should NOT use useLayoutEffect

CaseWhy it's bad
For API requests, timers, logsBlocks painting for no reason
For logic not related to the DOMMakes no sense
A frequently updating effectSlows down FPS - React waits for every layout effect to finish
During SSR (Next.js, etc.)React shows a warning: "useLayoutEffect does nothing on the server"

The ideal rule:

Use useLayoutEffect only for DOM operations that need to run before the user sees the screen. Everything else goes in useEffect.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.