Day 11: useEffect vs useLayoutEffect — Timing and Use Cases
- Published on
- • 2 mins read•--- views
When learning React, most developers start with useEffect. But sometimes you’ll see flickering in the UI, and that’s when useLayoutEffect comes in. So what’s the real difference between them?
Concept Explanation
useEffect: Runs after the DOM is updated and the browser has painted.- The user first sees the screen, then the effect runs.
- Good for async tasks like fetching data, event listeners, logging.
useLayoutEffect: Runs after the DOM is updated but before the paint.- The user only sees the final adjusted UI, no flicker.
- Good for DOM operations like measuring or adjusting elements.
Code Examples
useEffect may cause flicker
function Example() {
const ref = React.useRef(null);
React.useEffect(() => {
ref.current.style.backgroundColor = "yellow";
}, []);
return <div ref={ref}>Hello</div>;
}
➡️ The user first sees the original color, then it jumps to yellow.
useLayoutEffect avoids flicker
function Example() {
const ref = React.useRef(null);
React.useLayoutEffect(() => {
ref.current.style.backgroundColor = "yellow";
}, []);
return <div ref={ref}>Hello</div>;
}
➡️ The user immediately sees yellow, no jump.
Common Misunderstandings
- “All side effects should go into
useLayoutEffect.” → ❌ This blocks paint and hurts performance. - “I can measure DOM in
useEffect.” → ❌ You’ll read outdated values and cause flicker. - Official guidance: default to
useEffect, switch touseLayoutEffectonly when you need synchronous DOM operations.
Practical Use Cases
Handled by CSS (RWD) → Layout changes with media queries, no JS needed.
Needs
useLayoutEffect→- Measuring element size for animation or layout.
- Setting scroll position (e.g. chat app auto-scroll).
- Avoiding flicker in animations (e.g. fade-in).
- Integrating with DOM libraries like D3 or GSAP.
Small Exercise
Which hook would you use?
- Adjusting layout based on element width before showing UI.
- Sending an API request when the page loads.
- Auto-scrolling chat messages to the bottom.
Summary
useEffect→ after paint, async tasks, non-blocking.useLayoutEffect→ before paint, DOM sync tasks, no flicker.- Default to
useEffect, useuseLayoutEffectonly when DOM operations must run before paint.