Next.js 15 Hydration Mismatch Hatası Nasıl Çözülür? 5 Kesin Çözüm (2026)

01.01.2026 03:29 Haber

Next.js 15 ile çalışırken "Hydration failed because the initial UI does not match" hatası mı alıyorsunuz? Panik yapmayın! Alesta Web olarak bu rehberde hydration mismatch error'ün ne olduğunu ve nasıl çözüleceğini (how to fix) detaylıca anlatacağız. React 19 ile gelen değişiklikler bu hatayı daha da yaygın hale getirdi.

Hydration Nedir? (What is Hydration?)

Hydration, server-side rendering (SSR) yapan framework'lerde kritik bir kavramdır. Şöyle düşünün: Sunucu tarafında HTML oluşturulur ve tarayıcıya gönderilir. Sonra React, bu HTML'i "canlandırır" (hydrate eder) ve interaktif hale getirir. İşte bu sürece hydration denir.

Alesta Web olarak Next.js projelerinde bu hatayı sıkça görüyoruz. Hata mesajı genellikle şöyle görünür:

Hata Mesajı / Error Message:

Error: Hydration failed because the initial UI does not match
what was rendered on the server.

Warning: Text content does not match server-rendered HTML.
Server: "Hello World" Client: "Hello undefined"

See more info here: https://nextjs.org/docs/messages/react-hydration-error
⚠️ Dikkat / Warning:

Hydration error, sunucuda oluşturulan HTML ile client'ta oluşturulan HTML'in eşleşmediğini gösterir. Bu ciddi bir sorun olabilir çünkü UI tutarsızlıklarına yol açar!

Hata Nedenleri (Common Causes of Hydration Mismatch)

Hydration mismatch hatasının birçok nedeni olabilir. Alesta Web deneyimlerimize göre en yaygın nedenler şunlardır:

1. window/document Kullanımı Server Component'te

❌ Yanlış Kullanım / Wrong Usage:

// Bu kod hydration error verir!
function MyComponent() {
    const width = window.innerWidth; // ❌ Server'da window yok!
    return <div>Width: {width}</div>;
}

2. Tarih/Saat Bazlı İçerik (Date/Time Content)

❌ Yanlış Kullanım:

// Sunucu ve client farklı zaman gösterir
function Clock() {
    return <div>{new Date().toLocaleTimeString()}</div>; // ❌ Mismatch!
}

3. Random Değerler

❌ Yanlış Kullanım:

// Math.random() her seferinde farklı sonuç verir
function RandomGreeting() {
    const greetings = ['Merhaba', 'Selam', 'Hey'];
    const index = Math.floor(Math.random() * greetings.length);
    return <h1>{greetings[index]}</h1>; // ❌ Server vs Client farklı!
}

4. Browser Extension'lar (Özellikle Next.js 15 + React 19)

Next.js 15 ve React 19 kombinasyonunda bazı browser extension'lar HTML'e ekstra attribute ekler. Örneğin ColorZilla extension'ı cz-shortcut-listen="true" attribute'u ekler ve hydration error'a neden olur.

5. localStorage/sessionStorage Erken Erişim

❌ Yanlış Kullanım:

function UserPreferences() {
    // localStorage server'da mevcut değil!
    const theme = localStorage.getItem('theme'); // ❌ Error!
    return <div className={theme}>Content</div>;
}

Çözüm Yöntemleri (How to Fix Hydration Errors)

Alesta Web olarak yüzlerce projede bu hataları çözdük. İşte kanıtlanmış çözümler:

Yöntem 1: useEffect ile Client-Only Logic

✅ Doğru Kullanım / Correct Usage:

import { useState, useEffect } from 'react';

function WindowWidth() {
    const [width, setWidth] = useState(0);

    useEffect(() => {
        // Bu kod sadece client'ta çalışır
        setWidth(window.innerWidth);

        const handleResize = () => setWidth(window.innerWidth);
        window.addEventListener('resize', handleResize);

        return () => window.removeEventListener('resize', handleResize);
    }, []);

    // İlk render'da 0 göster (server ile eşleşir)
    if (width === 0) return null;

    return <div>Window width: {width}px</div>;
}

Yöntem 2: Dynamic Import ile SSR Devre Dışı

✅ SSR Kapatma / Disable SSR:

import dynamic from 'next/dynamic';

// Bu component sadece client'ta render edilir
const ClientOnlyMap = dynamic(() => import('./Map'), {
    ssr: false,
    loading: () => <p>Harita yükleniyor...</p>
});

function MapPage() {
    return (
        <div>
            <h1>Konum Haritası</h1>
            <ClientOnlyMap />
        </div>
    );
}

Yöntem 3: suppressHydrationWarning (Escape Hatch)

✅ Uyarıyı Bastırma / Suppress Warning:

// Sadece TEK SEVİYE derinliğinde çalışır
function DateDisplay() {
    return (
        <time suppressHydrationWarning>
            {new Date().toLocaleDateString()}
        </time>
    );
}

// UYARI: Bu bir escape hatch'tir, sorunu çözmez sadece gizler!
⚠️ Dikkat / Warning:

suppressHydrationWarning sadece kaçınılmaz durumlarda kullanılmalıdır. Sorunu çözmez, sadece uyarıyı gizler. Alesta Web olarak öncelikle asıl sorunu çözmenizi öneriyoruz.

Yöntem 4: next-themes için Özel Çözüm

Dark mode için next-themes kullanıyorsanız, hydration hatası çok yaygındır:

✅ next-themes Doğru Kurulum:

// app/providers.tsx
'use client';

import { ThemeProvider } from 'next-themes';

export function Providers({ children }) {
    return (
        <ThemeProvider
            attribute="class"
            defaultTheme="system"
            enableSystem
            disableTransitionOnChange
        >
            {children}
        </ThemeProvider>
    );
}

// Component'te kullanım
'use client';

import { useTheme } from 'next-themes';
import { useEffect, useState } from 'react';

function ThemeToggle() {
    const [mounted, setMounted] = useState(false);
    const { theme, setTheme } = useTheme();

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

    // Mounting öncesi render etme (hydration mismatch önlenir)
    if (!mounted) return null;

    return (
        <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
            {theme === 'dark' ? '?' : '☀️'}
        </button>
    );
}

Yöntem 5: Third-Party Script'leri Lazy Load

✅ Script Lazy Loading:

import Script from 'next/script';

function AnalyticsPage() {
    return (
        <>
            {/* afterInteractive: hydration sonrası yükle */}
            <Script
                src="https://www.googletagmanager.com/gtag/js?id=GA_ID"
                strategy="afterInteractive"
            />

            {/* lazyOnload: sayfa tamamen yüklendikten sonra */}
            <Script
                src="https://widget.example.com/embed.js"
                strategy="lazyOnload"
            />
        </>
    );
}

Pratik Örnekler (Real-World Examples)

Örnek 1: LocalStorage ile Kullanıcı Tercihi

✅ Güvenli localStorage Kullanımı:

'use client';

import { useState, useEffect } from 'react';

function useLocalStorage<T>(key: string, initialValue: T) {
    // Server'da initialValue kullan
    const [storedValue, setStoredValue] = useState<T>(initialValue);

    useEffect(() => {
        // Client'ta localStorage'dan oku
        try {
            const item = window.localStorage.getItem(key);
            if (item) {
                setStoredValue(JSON.parse(item));
            }
        } catch (error) {
            console.warn(`Error reading localStorage key "${key}":`, error);
        }
    }, [key]);

    const setValue = (value: T) => {
        setStoredValue(value);
        window.localStorage.setItem(key, JSON.stringify(value));
    };

    return [storedValue, setValue] as const;
}

// Kullanım
function Settings() {
    const [fontSize, setFontSize] = useLocalStorage('fontSize', 16);

    return (
        <div style={{ fontSize }}>
            <button onClick={() => setFontSize(fontSize + 2)}>Büyüt</button>
            <button onClick={() => setFontSize(fontSize - 2)}>Küçült</button>
        </div>
    );
}

Örnek 2: Mounted State Pattern

✅ Mounted Pattern:

'use client';

import { useState, useEffect } from 'react';

function ClientOnlyComponent({ children }) {
    const [hasMounted, setHasMounted] = useState(false);

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

    if (!hasMounted) {
        // Server ile aynı içeriği döndür (veya null)
        return null;
    }

    return <>{children}</>;
}

// Kullanım
function App() {
    return (
        <ClientOnlyComponent>
            <BrowserOnlyFeature />
        </ClientOnlyComponent>
    );
}

Best Practices (En İyi Uygulamalar)

Alesta Web olarak Next.js projelerinde şu kurallara uyuyoruz:

? Altın Kurallar / Golden Rules:
  • ✅ İlk render'ı server ve client'ta aynı tut
  • ✅ Browser API'lerini useEffect içinde kullan
  • ✅ Random/time-based değerleri client-side hesapla
  • ✅ SSR gerektirmeyen component'leri dynamic import ile yükle
  • ✅ Third-party script'leri afterInteractive stratejisi ile yükle

Debug İpuçları (Debugging Tips)

Hata Ayıklama / Debugging:

# React DevTools ile inspect et
# Console'da hydration uyarılarını ara

# SSR çıktısını kontrol et
curl -s http://localhost:3000 | grep -i "hydration"

# Build ve analiz
npm run build
# "Hydration" kelimesini içeren uyarıları kontrol et

? Kaynaklar ve Referanslar / Sources and References

Alesta Web olarak tüm çözümleri test ettik ve doğruladık.

✅ Sorun Çözüldü! (Problem Solved!)

Artık Next.js 15 hydration mismatch error (hydration hatası) sizin için bir sorun olmaktan çıktı! Alesta Web olarak anlattığımız yöntemlerle bu hatayı kolayca çözebilirsiniz.

Hızlı Özet / Quick Summary:

  • ✅ Hydration kavramı öğrenildi (Hydration concept learned)
  • ✅ Hata nedenleri belirlendi (Error causes identified)
  • ✅ 5 farklı çözüm yöntemi (5 different solution methods)
  • ✅ Best practices uygulandı (Best practices applied)

Faydalı Linkler / Useful Links:

© 2026 AlestaWeb - Tüm hakları saklıdır.

WM Tools
💫

WebMaster Tools

15 Profesyonel Araç