skip to content

Your React app is server-rendered, and a component calls useLayoutEffect. What happens to that effect during server rendering, and what would you do about it?

level: seniorimportance: should knowfreq 32%

answer

  1. the server emits markup, not a DOM
  2. nothing to measure, nothing to paint
  3. the warning names one hook, not both
  4. first paint is the server's frame
  5. the alias silences, it does not fix

basics

~20 s

Effects never run during server rendering, so useLayoutEffect is skipped and React logs a development warning about it. The server HTML carries the un-adjusted layout, and the correction happens only after hydration on the client.

solid answer

~50 s

Server rendering produces HTML, not a live DOM, so no effect of either kind runs there — the server renderer simply skips them. React warns about `useLayoutEffect` specifically because its whole purpose, adjusting the DOM before the browser paints, cannot be expressed in a string of markup. The practical consequence is what matters: the browser paints the server HTML in its pre-measurement state, and your correction only lands once the client has hydrated and run the layout effect. So the flicker you added the hook to prevent reappears on the first load. My preferred fix is to make the server-rendered markup not depend on a measurement — CSS-driven positioning, or an intrinsically correct default. If a measurement is genuinely unavoidable, gate the measured branch behind client-only rendering so the server emits a stable placeholder, and accept the extra render rather than pretending the server knows the layout.

go deeper

for a junior

Know the basic fact: effects do not run when React renders on the server, so anything a layout effect would adjust is missing from the HTML. Recognise the development warning when you see it in server logs.

for a middle

Explain why the server has nothing to measure, and why React warns for the layout hook but not the passive one. Describe the sequence: server HTML paints first, hydration runs later, the adjustment lands after the user has already seen the page.

for a senior

Weigh the fixes rather than reciting the alias. Argue for removing the measurement dependency where CSS can express the layout, for an explicit client-only branch where it cannot, and be clear that aliasing the hook silences a warning without improving the first paint.

for a principal

Treat it as a rendering-strategy question: how much of the visual result should depend on client measurement at all, what the team may ship in a server-rendered path, and what the cost is when the corrected frame arrives seconds after the first one on slow networks.

## Why no effect runs on the server Server rendering walks the component tree once and emits HTML. There is no document, no layout, nothing to measure, and no unmount that would ever call a cleanup. React therefore never invokes effect setups during a server render — neither `useEffect` nor `useLayoutEffect`. Only the render phase runs: the component function body, and hooks that produce a value such as `useState`'s initial state. This is a design consequence, not an omission. An effect exists to synchronise with something outside React's output, and the server produces no live thing to synchronise with. ## Why React singles out useLayoutEffect Development builds log a warning when a component using `useLayoutEffect` is server-rendered, saying it does nothing on the server because its effect cannot be encoded into the renderer's output format. `useEffect` gets no such warning, and the asymmetry is the interesting part: work deferred until after paint is obviously a client concern, so skipping it on the server surprises nobody. A layout effect, by contrast, usually exists to make the *first visible frame* correct — and that first frame, in a server-rendered app, is the server's HTML. Skipping it means the guarantee you thought you had does not hold where it matters most. ## What the user actually experiences Trace the sequence. The server sends HTML built without any measurement, so the markup contains whatever default your render produced — a tooltip on its provisional side, a container at its unmeasured height. The browser parses and **paints** that. Only afterwards does the client bundle load and hydrate; at that point the layout effect finally runs, measures, and updates. The correction is now a visible change to something the user has already seen. So the flicker is not merely unfixed — it is arguably worse than in a client-only app, because the gap between the first paint and hydration can be long on a slow connection. ## Fix one: remove the dependency on measurement The best outcome is markup that is right without being measured. Positioning that CSS can express — `position: sticky`, container queries, intrinsic sizing, an anchor-based layout — needs no round trip through JavaScript and is correct in the server's very first frame. A great deal of measure-and-adjust code exists because a layout was expressed imperatively when it could have been declarative. In a server-rendered app that refactor is not cosmetic; it is the difference between a correct first paint and a corrected one. ## Fix two: make the measured branch client-only When the measurement is genuinely irreducible, be explicit that the server cannot know the answer. Render a stable, measurement-free placeholder on the server, flip to the measured version after mount, and accept the extra client render. Two things make this honest rather than a hack: the server and the first client render must produce the *same* output, or hydration has a different problem on its hands; and the placeholder should be something you are content for the user to see, not a blank gap. ## Fix three: the isomorphic-layout-effect alias The widely copied workaround picks the hook by environment: ```js import { useEffect, useLayoutEffect } from 'react'; const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect; ``` Be precise about what this buys. Neither hook runs on the server, so this changes no behaviour there at all — its only effect is to silence the warning by making sure the server render never sees `useLayoutEffect`. That is legitimate for library code, which cannot control where it is rendered and should not spam a consumer's server logs. In application code it is worth pausing: the warning was pointing at a real gap in your first paint, and aliasing it away removes the message rather than the gap. ## What to say in the interview Lead with the mechanism — no effects on the server, so the markup is un-adjusted — then the user-visible consequence, then the fixes in order of honesty: eliminate the measurement, make it explicitly client-only, or alias the hook when you are shipping a library and the warning is the only real problem. Naming the alias without noting that it changes nothing functionally is the answer that sounds informed but is not.

  • Why does React warn about useLayoutEffect on the server but not about useEffect?
    Both are skipped, but only one implies a broken promise. useEffect is defined as work deferred past paint, so nobody expects it in a string of HTML. useLayoutEffect exists to make the first visible frame correct, and in a server-rendered app that first frame is the server's markup — so silently skipping it produces exactly the flicker the hook was chosen to prevent.
  • Does the isomorphic-layout-effect alias change any behaviour on the server?
    No. Neither hook runs during server rendering, so the alias is purely about which hook the server renderer sees, and therefore whether it warns. It is reasonable for library code that cannot control its environment; in application code it removes the message while leaving the un-adjusted first paint exactly as it was.
  • If you render the measured version only after mount, what must you be careful about?
    The server output and the first client render have to match, so the client's initial render must produce the placeholder too — flipping to the measured version in a later render, not during hydration. Otherwise you have traded a flicker for a hydration mismatch, and the placeholder should be something acceptable to look at, since users on slow connections will see it for a while.

saying these in an interview costs you the question

  • Thinks useEffect still runs during server rendering
  • Believes the warning means the effect runs twice on the server
  • Treats the isomorphic alias as fixing the missing adjustment
  • Says the server can measure element sizes for the first paint
  • Ignores that the browser paints server HTML before hydration

context