Hard15 minReact Fundamentals
UpdatedAug 1, 2026
Edit

useEffect vs useLayoutEffect

CONCEPTS:Browser Rendering Pipeline

Question Variations

  • "What is the difference between `useEffect` and `useLayoutEffect`?"
  • "When should you use `useLayoutEffect` instead of `useEffect`?"
  • "Why can `useLayoutEffect` cause performance issues or 'jank' in the UI?"
  • "How do these hooks interact with the browser's paint cycle?"

Why This Is Asked

This tests deep knowledge of React’s rendering pipeline and the browser paint cycle. Interviewers want to know if you understand when each hook fires relative to the browser paint, and whether you can identify the specific scenarios where useLayoutEffect is necessary (DOM measurements, flicker prevention).

Key Concepts

  • useEffect fires asynchronously after the browser has painted — it does not block visual updates
  • useLayoutEffect fires synchronously after DOM mutations but before the browser paints
  • Use useLayoutEffect when you need to measure or mutate the DOM before the user sees it (e.g., tooltips, scroll position, animations)
  • useLayoutEffect blocks the paint, so heavy computation in it causes visible jank
  • useLayoutEffect doesn’t run on the server — using it in SSR components triggers warnings

Question Variations

  • “What is the difference between useEffect and useLayoutEffect?”
  • “When should you use useLayoutEffect instead of useEffect?”
  • “Why can useLayoutEffect cause performance issues or ‘jank’ in the UI?”
  • “How do these hooks interact with the browser’s paint cycle?”

Answers by Technology

+ Add Variant
ReactImprove this answer ✏️

Expected Answer

The difference lies in the timing of execution relative to the browser’s paint cycle:

State Change / Trigger

React Render Phase

React Commit Phase / DOM Mutation

useLayoutEffect - Synchronous

Browser Paint

useEffect - Asynchronous

  1. useEffect (Asynchronous): Runs after the browser has painted the screen. It is non-blocking and is the default choice for most side effects like data fetching, subscriptions, or logging.
  2. useLayoutEffect (Synchronous): Runs after React has mutated the DOM but before the browser paints the changes. It blocks the paint, allowing you to measure layout and re-render synchronously to prevent visual flickering.

Why It Matters

Using the wrong effect can cause a poor user experience. If you use useEffect to adjust the position of a tooltip based on an element’s size, the user will see the tooltip appear in the wrong place for one frame, then jump to the right place (flicker). Using useLayoutEffect prevents this jump but can degrade performance if the effect logic takes too long, as the user will see a blank screen or a frozen UI.

Example Code

function Tooltip({ text }) {
  const [position, setPosition] = useState(0);
  const ref = useRef();

  useLayoutEffect(() => {
    // Measure DOM before the user sees the initial render
    const { width } = ref.current.getBoundingClientRect();
    setPosition(width / 2);
  }, []);

  return (
    <div ref={ref} style={{ left: position }}>
      {text}
    </div>
  );
}

Common Mistakes

  • Defaulting to useLayoutEffect: It should only be used for layout measurements. In 99% of cases, useEffect is the correct choice because it doesn’t block the UI.
  • SSR Hydration Mismatch: useLayoutEffect cannot run on the server. If a component uses it, it will trigger a warning during hydration because the server-rendered HTML won’t match the client’s first layout-adjusted render.

Follow-up Questions

  • What happens if you update state inside useLayoutEffect? (Answer: React will immediately perform a second render and diff, and only the final result will be painted to the screen).
  • Why does useEffect not cause a flicker for data fetching? (Answer: Because data fetching is already an asynchronous operation; the initial “Loading” state is painted, and the subsequent “Data” state is painted whenever the promise resolves).

References