The useLayoutEffect hook runs after the DOM has been updated but before the browser has had
a chance to paint the screen. This means you can make your measurements and then render the
UI with the correct measurements before the user sees anything.
| Hook | Timing | Blocking | Best For |
|---|---|---|---|
| useEffect | After paint | ❌ Non-blocking | Data fetching, subscriptions |
| useLayoutEffect | Before paint | ✅ Blocking | Layout reads/writes, DOM sync |
useLayoutEffect(() => {// your layout-effect code here.// this is where you read/write layout synchronously// e.g. measure DOM, set position, prevent flickerdoLayoutThing()return function cleanup() {// clean up layout-related side-effects// e.g. remove observers, cancel animationsdoSomeCleanup()}}, [// this is where dependencies of your useLayoutEffect callback go// any value used inside the effect should be listed heredep1,dep2,])
useLayoutEffect?Use it when you need to:
useLayoutEffect(() => {const height = ref.current.offsetHeight;setHeight(height);}, []);
useLayoutEffect(() => {window.scrollTo(0, savedPosition);}, []);
✔ Tooltip positioning
✔ Virtualized lists
✔ Sticky headers
✔ Canvas & chart rendering
❌ Using it for data fetching
❌ Using it without real layout dependency