Pindahkan useEffect dari Server Component ke Client Component kecil yang dipanggil lewat props. Page di app/ secara default berjalan di server tanpa lifecycle browser, jadi hook seperti useEffect, useState, dan akses window langsung ditolak.
Penyebab useEffect Ditolak di Server Component
Server Component dirender sekali di server untuk menghasilkan HTML. Proses itu tidak mengenal mount, update, atau unmount di browser.
useEffect justru dirancang berjalan setelah komponen tampil di browser. React membutuhkannya untuk:
- Menyimpan state dan menjalankan ulang efek saat dependency berubah
- Mengakses DOM,
window,document, danlocalStorage - Mendaftarkan event listener, timer, atau subscription
Error muncul ketika file tanpa use client mengimpor useEffect. Next.js membaca file itu sebagai Server Component dan menghentikan build atau render.
Tabel: Pola Error dan Arah Perbaikan
Tidak semua masalah efek diperbaiki dengan cara yang sama. Bedakan kode yang memang butuh browser dengan data yang bisa dibaca di server.
| Masalah | Penyebab | Solusi |
|---|---|---|
useEffect langsung di page |
Page adalah Server Component | Pindah efek ke komponen anak |
Akses window atau document |
API hanya ada di browser | Jalankan di Client Component |
Fetch berulang dengan useEffect |
Data bisa diambil saat render | Pakai async Server Component |
| Listener scroll atau resize | Butuh DOM dan cleanup | Isolasi di komponen interaktif |
Solusi: Pindahkan Efek ke Client Component Kecil
Pertahankan page sebagai Server Component. Bungkus hanya bagian interaktif dalam Client Component.
- Identifikasi UI yang benar-benar butuh efek, misalnya judul dokumen, animasi, atau listener.
- Buat file baru, tulis
use clientdi baris pertama, lalu pindahkanuseEffectke sana. - Kirim data awal dari server melalui props, bukan fetch ulang dari browser.
- Impor komponen client tersebut dari page server.
// app/dashboard/page.tsx
import TitleUpdater from "./title-updater";
export default async function Page() {
const username = "Ayu";
return <TitleUpdater username={username} />;
}
// app/dashboard/title-updater.tsx
"use client";
import { useEffect } from "react";
export default function TitleUpdater({ username }: { username: string }) {
useEffect(() => {
document.title = `Halo, ${username}`;
}, [username]);
return <p>Halo, {username}</p>;
}
Jangan mengubah seluruh page menjadi client hanya untuk satu efek. Pola itu membuang keuntungan render server dan cache App Router.
FAQ
Bisakah Server Component tetap fetch data tanpa useEffect?
Ya. Gunakan komponen async dan panggil fetch langsung saat render.
Kapan tetap butuh useEffect di Client Component?
Butuh untuk sinkronisasi browser seperti judul dokumen, listener, timer, dan library DOM.
Apakah semua error hook harus pakai use client di page?
Tidak. Tambahkan use client hanya di file komponen kecil yang memakai hook.