Skip to main content

What does useLayoutEffect() do during SSR?

A reminder: what useLayoutEffect() does in client-side React

useLayoutEffect() is the "synchronous" counterpart of useEffect():

HookWhen it fires
useEffect()already after the browser has painted the DOM (asynchronously)
useLayoutEffect()right after React updates the DOM, but before the screen paints

That means useLayoutEffect() lets you:

  • measure element sizes,
  • change the layout synchronously,
  • or perform DOM mutations before the user sees the screen.

What happens during SSR

During Server-Side Rendering, React has no access to the DOM.

  • No window,
  • no document,
  • no real elements.

So any DOM operations inside useLayoutEffect() are impossible.

That's why React doesn't call this hook at all on the server.


useLayoutEffect()'s behavior in SSR

On the server:

  • React fully ignores every useLayoutEffect() (and useEffect() too).
  • The code inside it never runs at all.
  • The component renders "cleanly" - it just returns JSX -> HTML.

On the client (after hydration):

  • React runs useLayoutEffect() once, once hydration finishes and the DOM is available.
  • If the hook contains side effects, they only fire after the HTML already exists in the browser.

A possible issue - a console warning

If you use useLayoutEffect() inside a component that renders both on the server and the client, React may print a warning:

javascript
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format.

or

javascript
Warning: useLayoutEffect is not supported during server rendering.

This isn't an error, just a warning: React is simply telling you that your layout effect will be ignored during SSR.


How to avoid the problem

Option 1. Replace useLayoutEffect with useEffect, if possible

If your code doesn't depend on precise DOM measurements, it's better to just use useEffect:

javascript
useEffect(() => { console.log('Safe for SSR'); }, []);

Option 2. Wrap the call in an environment check

If you still need useLayoutEffect (e.g. for canvas, measurements, and animations), you can safely define a "universal" hook:

javascript
import { useLayoutEffect, useEffect } from 'react'; // A safe hook for SSR export const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;

Now you can write:

javascript
useIsomorphicLayoutEffect(() => { const rect = ref.current.getBoundingClientRect(); console.log(rect); }, []);

On the server, useEffect runs (so nothing happens), and in the browser, the real useLayoutEffect runs.


Option 3. Run DOM-dependent code only after hydration

javascript
const [hydrated, setHydrated] = useState(false); useEffect(() => { setHydrated(true); }, []); if (!hydrated) return null; useLayoutEffect(() => { // This code only runs on the client, after hydration }, []);

Summary

EnvironmentWhat useLayoutEffect() does
Server (SSR)Fully ignored - not called, the DOM is unavailable
Client (after hydration)Runs synchronously after the HTML is inserted into the DOM
If used in an SSR componentMay trigger a warning, but not an error
SolutionUse useIsomorphicLayoutEffect or useEffect

The key takeaway

useLayoutEffect doesn't work on the server. React simply skips it during SSR, and only runs it after the HTML has already been rendered and "brought to life" on the client.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.