When useLayoutEffect Runs vs useEffect
Learn that useLayoutEffect fires synchronously after DOM mutations but before the browser paints.
When useLayoutEffect Runs vs useEffect is a free React Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
useLayoutEffect Timing
useLayoutEffect fires synchronously immediately after React has applied DOM mutations, but before the browser has had a chance to paint those changes. From the browser's perspective, the layout effect and the DOM mutations are part of the same uninterrupted synchronous block of work.
useEffect Timing
useEffect fires asynchronously after the browser has completed its paint. The user sees the updated UI first, and then the effect runs. This makes useEffect less disruptive to rendering performance, but means that any visible changes caused by the effect will result in a second paint cycle.
Timestamp Experiment
You can verify the timing difference by logging timestamps in both effects: add console.log('layout', Date.now()) in useLayoutEffect and console.log('passive', Date.now()) in useEffect. In the console, the layout effect timestamp will always be earlier than the passive effect timestamp, confirming the execution order.
Visible Consequences for Users
If a useEffect updates state that affects visual output, the user sees two renders: the initial render with stale state, then the corrected render after the effect fires. This manifests as a visible flash or reflow. useLayoutEffect prevents this because its state updates commit before the browser paints anything.
useLayoutEffect State Update Causes Synchronous Re-render
If you call setState inside a useLayoutEffect, React immediately runs another render and commit cycle before painting. The browser only paints the final result — the user never sees the intermediate state. This is the primary use case for useLayoutEffect: measure the DOM, compute a new value, set state, and guarantee one clean paint.
Performance Caveat
Because useLayoutEffect runs synchronously before paint and can trigger additional renders, excessive use can hurt performance. If the synchronous work is heavy, it blocks the browser from painting, causing visible jank. Only use it when you need to prevent a visual flash; use useEffect for everything else.
Strict Mode Double Invocation
In React Strict Mode (development only), both useLayoutEffect and useEffect are invoked twice per mount. The sequence is: mount, cleanup, mount again. This helps detect effects that do not clean up properly. The double invocation does not happen in production builds.
Performance Rule: Default to useEffect
The default choice should always be useEffect. Only switch to useLayoutEffect when you can observe and reproduce a visual flickering or incorrect layout problem. Overusing useLayoutEffect blocks the browser painting pipeline unnecessarily and can degrade perceived performance.
SSR Caveat: useLayoutEffect on Server
useLayoutEffect cannot run on the server because there is no DOM or browser paint cycle in a server environment. If used in a component that renders on the server, React emits a warning. The fix is to conditionally skip the effect: check typeof window !== 'undefined' or switch to useEffect for SSR-compatible code.
Diagnosing Which to Use
Ask yourself: "Does this effect change something that the user will see on the very first paint?" If yes, use useLayoutEffect to prevent a flash. If no — for data fetching, subscriptions, analytics, logging, and most other side effects — use useEffect. This decision framework covers the majority of real-world cases.
The Synchronous Nature of useLayoutEffect
useLayoutEffect runs in the same synchronous block as the DOM mutations. React cannot process other work (like responding to user events) while a useLayoutEffect is running. This is why it must be fast and focused. Long-running synchronous code in useLayoutEffect directly delays the browser from rendering to the screen.
useLayoutEffect Timing
When exactly does useLayoutEffect fire relative to DOM mutations and browser paint?
Lesson Recap: useLayoutEffect vs useEffect
useLayoutEffect is synchronous and fires before browser paint, making it suitable for DOM measurement and visual corrections. useEffect fires after paint and is the right choice for data fetching, subscriptions, and most side effects. Default to useEffect and only switch when visual flickering confirms useLayoutEffect is needed. Avoid it in SSR without guards.
Frequently asked questions
Is the “When useLayoutEffect Runs vs useEffect” lesson free?
Yes — the full text of “When useLayoutEffect Runs vs useEffect” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “When useLayoutEffect Runs vs useEffect”?
Learn that useLayoutEffect fires synchronously after DOM mutations but before the browser paints. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “When useLayoutEffect Runs vs useEffect” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Rendering Phase and DOM Commit
- When useLayoutEffect Runs vs useEffect
- Measuring DOM Elements with useLayoutEffect
- Avoiding Layout Thrash and Visual Flicker