BitlystBitlyst
PostsSeriesTopicsAbout

Bitlyst

Short, diagram-first posts on JavaScript, React & Next.js. Follow via RSS or the newsletter.

© 2026 Mohsen Fallahnejad

PostsSeriesTopicsLinksAboutRSSGitHubX
Posts/react
Intermediate2 min read

Why setState Doesn’t Cause Hydration Errors

Understanding why calling setState after hydration doesn’t produce hydration mismatches in React/Next.js.

Mohsen Fallahnejad

Mohsen Fallahnejad

Sep 26, 2025Discuss

🚀 The Core Idea#

Hydration errors happen only if the first client render output doesn’t match the server-rendered HTML.
Most setState calls you write run after hydration is finished, so React treats them as normal updates, not as mismatches.


🕒 Timeline of hydration#

  1. Server render

    • HTML is generated on the server and sent to the browser.
  2. Client boot

    • React runs the first client render and hydrates the existing DOM.
    • It compares this client render output with the server HTML.
    • If they differ, React shows a hydration mismatch warning.
  3. After hydration

    • useEffect callbacks run.
    • User events (clicks, inputs) happen.
    • Calling setState here triggers a normal re-render; React patches the DOM without comparing to the server again.

✅ So if your initial client render matches the server, later setState calls will not cause hydration errors.


❌ When you do get hydration errors#

Hydration warnings occur if the first client render differs from the server HTML. Common causes include:

  • Non-deterministic values during render

    js
    // BAD: server vs client will produce different numbers
    const id = Math.random();
    
  • Browser-only values in render

    js
    // BAD: only available on client
    const width = window.innerWidth;
    
  • Different data fetching paths between server and client.


✅ Safe Patterns#

1. Update inside useEffect#

tsx
"use client";
import { useState, useEffect } from "react";

export default function Example() {
  const [theme, setTheme] = useState<string | null>(null); // null matches server
  useEffect(() => {
    setTheme(window.localStorage.getItem("theme")); // runs after hydration
  }, []);
  return <div>Theme: {theme ?? "system"}</div>;
}

2. Mounted flag for client-only UI#

tsx
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);

if (!mounted) return null; // matches server's "nothing"
return <ClientOnlyUI />;

3. Disable SSR for the component#

In Next.js, you can skip SSR entirely:

tsx
import dynamic from "next/dynamic";

const ClientComponent = dynamic(() => import("./ClientComponent"), { ssr: false });

4. Suppress warnings (last resort)#

For known benign differences, use:

tsx
<span suppressHydrationWarning>{clientOnlyValue}</span>

🧠 Mental Model#

  • Hydration compares only once: server HTML vs first client render.
  • setState after hydration = normal re-render, no mismatch.

So: make sure your first render is deterministic, and you’re safe.

Filed under#react#hydration#setState#nextjs

Was this worth your time?

One tap tells me what to write more of.

Mohsen Fallahnejad

Written by

Mohsen Fallahnejad

Frontend engineer explaining JavaScript, React & Next.js internals in posts you can finish over coffee. More about me

X ↗GitHub ↗LinkedIn ↗
← OlderAbortController & AbortSignalNewer →Deep Copy vs Shallow Copy in JavaScript

Start the discussion

Questions, corrections, a better approach? I read and reply to every comment.

Read next

The Server Action That Ran Twice, but Only on localhost

Why a Next.js Server Action called from useEffect runs twice in development: React Strict Mode mounts every component twice. What that reveals, and where the call belongs.

Nov 3, 20264 min read

I Optimized a Button From O(n) to O(1). The Speed Didn't Matter.

A bug report, a route map, and three rounds of making it faster — a story about what Big O really measures, why constants win at small n, and why the best algorithm is sometimes deleting the question.

Oct 31, 202610 min read6

Why MUI Avoids Theme Flash on First Load (Dark/Light Mode)

How MUI applies the correct color scheme on the very first paint, and why other UI kits often flash light before switching to dark.

Sep 29, 20253 min read1

Get new posts in your inbox

No spam. Unsubscribe any time.

2 min left
Discuss👍 React
👍