≡ Menu

🌊 Stop The Hydration Crisis: The Simple Fix For Window Is Undefined Errors

If you’ve built a React application using Server-Side Rendering (SSR), you’ve inevitably run into the frustrating Hydration Mismatch error.

This often happens when your component needs to render something that relies on browser-specific objects like window or localStorage.

The error occurs because the server, which renders your initial HTML, has no idea what window.innerWidth is.

When the client-side JavaScript loads and tries to “hydrate” (or attach interactivity to) the server-rendered HTML, it finds a structural difference in the DOM and throws a fit, often wiping the screen and starting over.

This defeats the purpose of SSR!

Fortunately, the fix is elegant and simple: defer all client-specific logic until after hydration is complete.


The Code Fix: useState and useEffect as Gatekeepers

 

This component structure uses a clever combination of the useState and useEffect hooks to safely access the browser environment without causing a server-client mismatch.

import React, { useState, useEffect } from 'react';

function LayoutCheckFixed() {
  // 1. Initial State: The hydration "gate"
  const [isMobile, setIsMobile] = useState(false); 
  const [hasMounted, setHasMounted] = useState(false); 

  // 2. useEffect: The client-only trigger
  useEffect(() => {
    // ONLY runs on the client, after the initial render.
    const checkIsMobile = window.innerWidth < 768;
    setIsMobile(checkIsMobile);
    setHasMounted(true); // Open the gate!
  }, []); 

  // 3. Conditional Render: The Hydration "Placeholder"
  if (!hasMounted) {
    return null// Server and initial client render must match this!
  }

  // 4. Final Render: The stable, client-specific output
  if (isMobile) {
    return <div>Mobile Layout</div>;
  } else {
    return <div>Desktop Layout</div>;
  }
}

🚀 How the Hydration-Safe Component is Processed

 

Understanding the sequence is key to mastering SSR. The code works because the server ignores useEffect, and the client’s initial render output matches the server’s output perfectly.

Phase 1: Server-Side Rendering (SSR) 🖥

 

  1. State Initialization: isMobile is false, and hasMounted is false.

  2. useEffect Ignored: The server skips the entire useEffect block; it never tries to access window.innerWidth.

  3. Conditional Check (Step 3): Since hasMounted is false, the component immediately returns null.

  4. HTML Output: The server sends HTML containing an empty space (the result of rendering null) for this component. This is stable and safe.

Phase 2: Client-Side Hydration 🌐

 

  1. Client Initial Render: The client-side React code runs. It finds the same initial state (hasMounted is false and also returns null.

  2. Hydration Success: React compares the client’s null with the server’s null. They match perfectly! Hydration is successful, and the app becomes interactive.

  3. useEffect Execution: Only now does the useEffect hook run.

    • It safely checks the real window.innerWidth.

    • It sets the correct isMobile state.

    • Crucially, it sets setHasMounted to true.

  4. Final Re-Render: The state change triggers a final, correct re-render. The component skips the return null check and renders the final, stable, client-specific output (Mobile Layout or Desktop Layout).

By delaying the logic that causes the mismatch, you ensure a smooth, single hydration pass, preserving the performance benefits of Server-Side Rendering. Happy hydrating!

Useful links below:

Let me & my team build you a money making website/blog for your business https://bit.ly/tnrwebsite_service

Get Bluehost hosting for as little as $1.99/month (save 75%)…https://bit.ly/3C1fZd2

Best email marketing automation solution on the market! http://www.aweber.com/?373860

Build high converting sales funnels with a few simple clicks of your mouse! https://bit.ly/484YV29

Join my Patreon for one-on-one coaching and help with your coding…https://www.patreon.com/c/TyronneRatcliff

Buy me a coffee ☕️https://buymeacoffee.com/tyronneratcliff

{ 0 comments… add one }

Leave a Comment