Render state awal netral dulu, lalu baca localStorage di dalam useEffect dan tampilkan nilainya setelah komponen mounted. Cara ini menyamakan HTML hasil render server dengan render pertama browser, sehingga pesan hydration mismatch hilang. Langkah yang paling sering terlewat adalah tetap memasang nilai awal kosong atau bawaan saat render pertama.
Penyebab Hydration Error saat Baca localStorage
Server tidak punya localStorage. Browser punya. Kalau render pertama memakai isi simpanan browser, hasilnya beda dari HTML server.
- State awal memanggil
localStorage.getItemlangsung saat render. - Komponen membaca tema, token, bahasa, atau preferensi sebelum mounted.
- Render memakai nilai acak, jam, atau data browser lain yang tidak ada di server.
Tabel Diagnosis Cepat Hydration Mismatch
| Gejala | Pemicu | Arah Perbaikan |
|---|---|---|
| Teks berubah setelah refresh | Tema dari localStorage | Gunakan state netral plus guard mounted |
| Error hanya setelah login | Token dibaca saat render | Baca token di useEffect, tampilkan loading netral |
| Beda tiap render | Date.now atau Math.random | Pindah ke useEffect atau ke server |
Pola Aman Pakai localStorage di Client Component
- Buat state awal netral, misalnya string kosong atau tema bawaan.
- Baca
localStoragehanya di dalamuseEffect. - Tambah flag
mounted, render konten tersimpan setelah nilainya true.
"use client";
import { useEffect, useState } from "react";
export default function ThemeLabel() {
const [theme, setTheme] = useState("light");
const [mounted, setMounted] = useState(false);
useEffect(() => {
const saved = localStorage.getItem("theme");
if (saved === "dark" || saved === "light") {
setTheme(saved);
}
setMounted(true);
}, []);
if (!mounted) {
return Memuat tampilan...
;
}
return Tema aktif: {theme}
;
}
- Jangan panggil
window,document, ataulocalStoragesaat render. - Jangan menganggap
use clientotomatis mencegah hydration error. - Simpan perubahan kembali dengan
localStorage.setItemdari event atau effect.
FAQ
Kenapa localStorage memicu hydration error padahal sudah pakai use client?
Client Component tetap dirender awal oleh server, sehingga bacaan browser saat render membuat HTML berbeda.
Apakah aman cek typeof window saat render untuk ambil localStorage?
Tidak aman karena server dan browser tetap dapat menghasilkan output berbeda dan mismatch berlanjut.
Bagaimana menampilkan data tersimpan tanpa kedip tampilan?
Tampilkan kerangka netral yang ukurannya sama, lalu ganti dengan nilai tersimpan setelah mounted.