Loop render di App Router hampir selalu berasal dari Client Component yang mengubah state lalu memicu efek yang sama berulang kali. Hentikan dulu siklusnya: kunci useEffect dengan deps stabil, jangan membuat objek atau array baru di setiap render, dan jangan meletakkan setState di dalam efek yang bergantung pada state itu sendiri.
Penyebab Client Component Rerender Terus di App Router
React me-render ulang saat state, props, atau context berubah. Masalah muncul ketika nilai itu terlihat baru padahal isinya sama.
- State diinisialisasi dengan
{},[],new Date(), atauMath.random()langsung di body komponen. useEffecttanpa array deps atau memakai deps objek baru, lalu memanggilfetchdansetState.- Fungsi handler dan objek props dibuat ulang setiap render, lalu dibaca ulang oleh komponen anak.
- Context value dibuat inline sehingga semua konsumen ikut render ulang.
- Pembacaan
useSearchParamsatau router yang berubah memicu fetch berantai di komponen client besar.
Tabel Diagnosis Rerender Berulang
Bedakan render wajar karena input pengguna dengan loop karena efek dan referensi tidak stabil.
| Gejala | Pemicu | Pemeriksaan cepat |
|---|---|---|
| Fetch jalan terus | Deps efek tidak stabil | Cek array deps dan log URL fetch |
| Input lag atau flicker | State besar di komponen induk | Pecah input ke komponen kecil |
| CPU naik, tab berat | Objek baru tiap render | Cari literal objek di props |
| Loop tanpa henti | Efek mengubah deps-nya | Hapus setState dari efek |
Cara Mengatasi Client Component Rerender Terus Langkah per Langkah
Validasi dengan React DevTools Profiler dulu sebelum menambah memo. Catat komponen yang render berulang, lalu perbaiki sumbernya.
- Isolasi bagian interaktif kecil sebagai Client Component di bawah Server Component. Biarkan data statis diambil di server.
- Perbaiki
useEffect: beri deps minimal, pindahkan fetch keluar bila tidak perlu efek, dan hindarisetStateyang memicu efek yang sama. - Stabilkan props dengan
useMemountuk objek,useCallbackuntuk handler, danmemohanya untuk komponen anak yang render-nya mahal. - Uji lagi di Profiler. Render harus turun tanpa mengubah hasil data.
"use client";
import { useEffect, useState } from "react";
export default function UserList({ query }: { query: string }) {
const [users, setUsers] = useState<string[]>([]);
useEffect(() => {
let active = true;
async function load() {
const res = await fetch(`/api/users?query=${query}`);
const data = await res.json();
if (active) setUsers(data.users);
}
load();
return () => {
active = false;
};
}, [query]);
return (
<ul>
{users.map((u) => (
<li key={u}>{u}</li>
))}
</ul>
);
}
FAQ
Apakah useMemo selalu menghentikan rerender?
Tidak. Ia hanya membantu bila referensi props stabil dan render anak memang mahal.
Kenapa data fetch berulang terus?
Biasanya efek jalan ulang karena deps tidak stabil atau setState memicu efek yang sama lagi.
Kapan pisah ke Server Component?
Saat data bisa diambil di server dan hanya tombol, input, atau interaksi kecil yang butuh client.