How to fix Warning: useLayoutEffect should not be used on the server because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. in React

ReactINTERMEDIATEMEDIUMUpdated Dec 10, 2025ยท 117 views

This warning appears when React detects useLayoutEffect during server-side rendering. Since layout effects require a DOM to measure and manipulate, they cannot run on the server, leading to potential hydration mismatches between server and client renders.

Quick fix

Fixes Warning: useLayoutEffect should not be used on the server because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI.

// lib/hooks/useIsomorphicLayoutEffect.ts
import { useEffect, useLayoutEffect } from 'react';

const useIsomorphicLayoutEffect =
  typeof window !== 'undefined' ? useLayoutEffect : useEffect;

export default useIsomorphicLayoutEffect;
  1. Create a useIsomorphicLayoutEffect custom hook
  2. Replace useLayoutEffect with useEffect for non-critical updates
  3. Delay component rendering until after hydration
  4. Mark components as client-only in Next.js
react โ€” error
// lib/hooks/useIsomorphicLayoutEffect.ts
import { useEffect, useLayoutEffect } from 'react';
const useIsomorphicLayoutEffect =
typeof window !== 'undefined' ? useLayoutEffect : useEffect;
export default useIsomorphicLayoutEffect;
Warning: useLayoutEffect should not be used on the server because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI.

What this error means

This warning occurs when you use React's useLayoutEffect hook in a component that is being server-side rendered (SSR). The useLayoutEffect hook is specifically designed to run synchronously after all DOM mutations but before the browser paints the screen. This timing allows components to read layout information (like element dimensions, positions, or scroll offsets) and synchronously re-render if needed before the user sees anything. However, during server-side rendering, there is no actual DOM, no layout information, and no browser paint cycle. The server is generating static HTML strings, not manipulating live DOM nodes. When React encounters useLayoutEffect during server rendering, it cannot execute the effect because the underlying browser APIs (like getBoundingClientRect, offsetWidth, etc.) don't exist in the Node.js environment. React warns about this because it creates a fundamental mismatch: the server-rendered HTML won't include any changes that useLayoutEffect would make, but when the component hydrates on the client, useLayoutEffect will run and potentially change the UI. This can cause visual "jumps" or layout shifts as content repositions itself after hydration, or worse, hydration errors if the mismatch is too significant.

Typical symptoms

  • Console warning "useLayoutEffect should not be used on the server" during SSR builds
  • Hydration mismatch warnings when the page loads in the browser
  • Visual content "jumps" or shifts position after initial page load
  • Flash of unstyled or incorrectly positioned content
  • Warning appears in Next.js builds during `next build` or `next dev`
  • Components render differently on initial server load versus after hydration
  • Third-party libraries trigger warnings when used in SSR environments
  • Build processes show warnings when using frameworks like Next.js, Remix, or Gatsby

Common causes

  1. Using useLayoutEffect directly in components that render on the server
  2. Third-party libraries (react-redux, framer-motion, react-dnd, react-hook-form) using useLayoutEffect internally
  3. Measuring DOM elements or reading layout information during server rendering
  4. Manipulating DOM nodes or reading browser-only APIs in useLayoutEffect
  5. Not distinguishing between server and client rendering environments
  6. Using useLayoutEffect to set state based on window dimensions or other browser APIs
  7. Component libraries that depend on layout measurements (tooltips, popovers, modals)
  8. Migrating from client-only React app to SSR framework without updating hooks

How to fix "Warning: useLayoutEffect should not be used on the server because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI."

1Create a useIsomorphicLayoutEffect custom hook

The most widely adopted solution is to create a custom hook that uses useLayoutEffect on the client and useEffect on the server. This pattern is used by many popular libraries like react-redux and react-beautiful-dnd:

typescript
// lib/hooks/useIsomorphicLayoutEffect.ts
import { useEffect, useLayoutEffect } from 'react';

const useIsomorphicLayoutEffect =
  typeof window !== 'undefined' ? useLayoutEffect : useEffect;

export default useIsomorphicLayoutEffect;

Then replace all useLayoutEffect calls with this custom hook:

typescript
import useIsomorphicLayoutEffect from '@/lib/hooks/useIsomorphicLayoutEffect';

function MyComponent() {
  useIsomorphicLayoutEffect(() => {
    // Your layout effect logic
    const element = document.getElementById('my-element');
    const height = element?.offsetHeight;
    // ...
  }, []);
}

This eliminates the warning while maintaining synchronous layout reading on the client.

2Replace useLayoutEffect with useEffect for non-critical updates

If your effect doesn't need to run before the browser paints (e.g., logging, data fetching, subscriptions), simply replace useLayoutEffect with useEffect:

typescript
// Before
import { useLayoutEffect } from 'react';

function MyComponent() {
  useLayoutEffect(() => {
    console.log('Component mounted');
  }, []);
}

// After
import { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('Component mounted');
  }, []);
}

useEffect runs asynchronously after the paint, preventing the server warning and avoiding blocking the initial render. Use this when:
- You're not reading layout information
- A brief flash of content is acceptable
- The effect doesn't need to block visual updates

3Delay component rendering until after hydration

For components that absolutely need layout effects, render them only after the client has hydrated:

typescript
import { useEffect, useState, useLayoutEffect } from 'react';

function ComponentWithLayoutEffect() {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  useLayoutEffect(() => {
    if (!isClient) return;
    // Safe to use layout effect now
    const element = document.getElementById('my-element');
    const rect = element?.getBoundingClientRect();
    // ...
  }, [isClient]);

  if (!isClient) {
    return <div>Loading...</div>; // Fallback for SSR
  }

  return <div>{/* Actual content with layout effects */}</div>;
}

This ensures the server and client render the same initial HTML (the loading state), then switches to the real content only on the client.

4Mark components as client-only in Next.js

In Next.js, use dynamic imports with ssr: false to prevent server-side rendering of components that use layout effects:

typescript
// app/page.tsx
import dynamic from 'next/dynamic';

const ClientOnlyComponent = dynamic(
  () => import('@/components/ComponentWithLayoutEffect'),
  { ssr: false }
);

export default function Page() {
  return (
    <div>
      <h1>My Page</h1>
      <ClientOnlyComponent />
    </div>
  );
}

In the component:

typescript
// components/ComponentWithLayoutEffect.tsx
'use client';

import { useLayoutEffect, useState } from 'react';

export default function ComponentWithLayoutEffect() {
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });

  useLayoutEffect(() => {
    // No warning - this only runs on client
    setDimensions({
      width: window.innerWidth,
      height: window.innerHeight
    });
  }, []);

  return <div>Window: {dimensions.width}x{dimensions.height}</div>;
}

The "use client" directive and ssr: false ensure the component only renders on the client.

5Use Suspense boundaries for gradual hydration

Wrap components using layout effects in Suspense boundaries to defer their rendering until client hydration:

typescript
import { Suspense } from 'react';

function Page() {
  return (
    <div>
      <h1>Content above suspense renders immediately</h1>
      <Suspense fallback={<div>Loading interactive content...</div>}>
        <ComponentWithLayoutEffect />
      </Suspense>
    </div>
  );
}

This allows the server to render a fallback while the component with layout effects only renders on the client after hydration. In React 18+, this pattern is particularly effective with streaming SSR.

6Update third-party libraries to SSR-compatible versions

Many libraries have fixed SSR compatibility in recent versions. Check and update:

bash
# Check current versions
npm list react-redux framer-motion react-hook-form

# Update to latest versions
npm install react-redux@latest framer-motion@latest react-hook-form@latest

Common libraries and their SSR fixes:
- react-redux v7.1+: Added useIsomorphicLayoutEffect internally
- framer-motion v6+: Improved SSR support
- react-hook-form v7+: Better SSR compatibility
- recharts v2+: Fixed useLayoutEffect warnings

If a library still causes warnings, check its GitHub issues for SSR workarounds or consider opening an issue.

Advanced notes

Why React specifically warns about useLayoutEffect: While both useEffect and useLayoutEffect cannot affect server-rendered output, React specifically warns about useLayoutEffect because it's designed to run synchronously before paint. Using it during SSR creates an unavoidable mismatch - the server has no DOM to measure, but the client will measure and potentially re-render before the user sees anything, causing layout shifts.

Performance considerations: useLayoutEffect blocks the browser from painting until the effect completes. On the server, this doesn't matter (no browser), but on the client, it can delay time-to-first-paint. Only use useLayoutEffect when you must prevent visual flashing (e.g., tooltip positioning, DOM measurements for animations). For most cases, useEffect is sufficient.

React 18 and Suspense: In React 18, Suspense handles client-only rendering more gracefully. You can mark components as client-only by placing them inside Suspense boundaries, and React will skip server rendering them automatically.

The isomorphic layout effect debate: There's ongoing discussion about whether useIsomorphicLayoutEffect is semantically correct. Some argue it's a pragmatic solution, while others suggest it can hide real bugs. The key insight: if your effect truly needs layout measurements, it probably shouldn't run on the server at all. Consider whether delaying rendering (Step 3) is more appropriate.

Next.js App Router specific: Next.js 13+ with App Router uses Server Components by default, which never run client hooks. Add "use client" at the top of files using useLayoutEffect, and Next.js will handle client-only rendering automatically. However, you still need to handle third-party libraries that might use useLayoutEffect internally.

Frequently asked questions

What does "Warning: useLayoutEffect should not be used on the server because its" mean?
This warning occurs when you use React's useLayoutEffect hook in a component that is being server-side rendered (SSR). The useLayoutEffect hook is specifically designed to run synchronously after all DOM mutations but before the browser paints the screen. This timing allows components to read layout information (like element dimensions, positions, or scroll offsets) and synchronously re-render if needed before the user sees anything.
How do I fix "Warning: useLayoutEffect should not be used on the server because its"?
This warning appears when React detects useLayoutEffect during server-side rendering. Since layout effects require a DOM to measure and manipulate, they cannot run on the server, leading to potential hydration mismatches between server and client renders.
What causes "Warning: useLayoutEffect should not be used on the server because its"?
Using useLayoutEffect directly in components that render on the server Third-party libraries (react-redux, framer-motion, react-dnd, react-hook-form) using useLayoutEffect internally Measuring DOM elements or reading layout information during server rendering
Is the "Warning: useLayoutEffect should not be used on the server because its" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading