Hydration React SSR kerap menyebabkan tampilan berkedip ketika komponen client mengubah DOM setelah data tambahan di-fetch. Solusi utamanya adalah memastikan bahwa data dan state yang digunakan saat server render sama persis dengan yang digunakan saat hydrating di client.
Artikel ini membahas akar permasalahan render mismatch, cara reproduksi, debugging, pola penyiapan state konsisten, contoh Next.js sebelum/ sesudah perbaikan, serta checklist mitigasi agar UI tetap stabil.
Mengapa Hydration React SSR Bisa Sebabkan UI Blink
Render mismatch terjadi ketika DOM awal dari server tidak sama dengan hasil render saat React menghidupkan komponen di browser. Bila client-side effect (useEffect) langsung mengganti state dengan data baru, React akan merender ulang dan browser memperlihatkan perbedaan visual, alias blink.
Kondisi ini umum terjadi saat data hanya tersedia setelah client fetch, sementara server render tidak menyertakan data itu. Hydration React SSR akan membaca HTML statis, lalu menulis ulang DOM begitu state berubah, menyebabkan pemuatan berdampingan.
Gejala dan Reproduksi Render Mismatch
Gejala Umum
- Komponen yang tampak stabil di server tiba-tiba berubah bentuk, teks, atau placeholder setelah beberapa milidetik.
- Console menampilkan warning seperti "Text content did not match" atau "Prop `className` did not match".
- Network menunjukkan fetch tambahan berjalan segera setelah halaman tampil.
Reproduksi Sederhana
Gunakan komponen dengan state default kosong yang kemudian diperbarui di useEffect untuk mengambil data:
function Profile() {
const [name, setName] = useState('Loading...');
useEffect(() => {
fetch('/api/profile').then(res => res.json()).then(data => setName(data.name));
}, []);
return <div>Halo, {name}</div>;
}
Server render menampilkan "Loading..." sementara client fetch lalu mengganti ke nama sebenarnya. Selisih ini bisa memicu blink jika HTML awal sudah disimpan.
Strategi Menyamakan State untuk UI Stabil
Tujuan inti: data yang dipakai saat server render harus sama saat hydrating di client. Strategi yang umum diterapkan:
- Prefetch data di server (melalui
getServerSidePropsataugetStaticProps) dan kirim ke client sebagai props. - Gunakan fallback state yang identik di client (misalnya inisialisasi state dengan props server, bukan placeholder berbeda).
- Hindari efek client-only yang langsung mengubah DOM yang sudah ditentukan selama hydrating.
Contoh Next.js: Sebelum dan Sesudah Perbaikan
Sebelum: state diinisialisasi dengan placeholder dan data baru di-fetch di client.
export default function Profile() {
const [name, setName] = useState('Loading...');
useEffect(() => {
fetch('/api/profile').then(res => res.json()).then(data => setName(data.name));
}, []);
return <p>Halo, {name}</p>;
}
Sesudah: data diambil di server dan diberikan sebagai props.
export async function getServerSideProps() {
const res = await fetch('https://internal/api/profile');
const profile = await res.json();
return { props: { profile } };
}
export default function Profile({ profile }) {
const [name] = useState(profile.name);
return <p>Halo, {name}</p>;
}
Dengan cara ini, HTML awal dan state saat hidrasi identik sehingga tidak ada perubahan visual. Jika perlu interaksi client untuk memperbarui data, gunakan pola useEffect dengan logika fallback yang tidak mengacak struktur DOM yang sama.
Pola Penyiapan State Konsisten
- Prop drilling dari server: kirim data langsung sebagai prop dan inisialisasi state client dengannya.
- Gunakan context atau store yang dibangun ulang dari props server: jangan biarkan efek client mengganti state utama sampai fetch selesai.
- Hindari DOM-dependent effects: efek yang mengubah ukuran, animasi, atau kelas CSS sebaiknya dijalankan setelah state stabil.
Checklist Mitigasi Hydration Blink
- Apakah data ditarik di server dan disalurkan secara eksplisit ke komponen?
- Apakah state initial sama baik saat server maupun client (hindari placeholder berbeda)?
- Apakah ada efek client-only yang berjalan sebelum data sudah lengkap?
- Apakah fallback loading disiapkan tanpa mengubah struktur HTML secara drastis?
- Apakah komponen dibungkus dengan suspense atau skeleton yang statis untuk transisi halus?
Alat dan Teknik Debugging
Untuk memverifikasi apakah Hydration React SSR menyebabkan blink:
- React DevTools: Periksa apakah state dan props saat hydrasi sesuai dengan nilai yang dikirim dari server. Mode Strict bisa memperlihatkan rerender tambahan akibat mismatch.
- Console Hydration Warnings: Browser sering menampilkan warning seperti "Warning: Text content did not match". Tangkap log ini untuk mengidentifikasi elemen bermasalah.
- Tab Network: Amati apakah fetch berlangsung segera setelah halaman render pertama; jika ya, pastikan data tersebut sebenarnya sudah tersedia server-side.
Diagnosis realistis dimulai dengan mencatat fitur mana yang men-trigger state update di client serta memastikan data utama tersedia sejak server render. Setelah itu, refactor ke pola server props + client state inisialisasi untuk menyingkirkan blink.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!