Performa: memo, useMemo & useCallback
Mencegah render ulang yang tidak perlu dengan React.memo, useCallback, dan useMemo.
Render ulang itu normal
Saat state sebuah komponen berubah, React merender ulang komponen itu dan semua anaknya. Biasanya ini sangat cepat dan tidak perlu dikhawatirkan. Optimasi hanya perlu bila kamu mengukur adanya masalah (UI terasa lambat).
> Aturan: ukur dulu (React DevTools Profiler), baru optimalkan.
React.memo
React.memo membungkus komponen agar dilewati render ulangnya jika props tidak berubah:
const Anak = React.memo(function Anak({ nama, onKlik }) {
console.log("Anak dirender");
return <button onClick={onKlik}>{nama}</button>;
});
Mengapa memo kadang "tidak bekerja"?
Props dibandingkan dengan perbandingan dangkal (===). Function dan object yang dibuat ulang di setiap render selalu dianggap berbeda:
function Induk() {
const [n, setN] = useState(0);
const handle = () => console.log("hai"); // dibuat ulang tiap render!
return <Anak nama="A" onKlik={handle} />; // memo percuma
}
useCallback: menjaga referensi function
const handle = useCallback(() => console.log("hai"), []);
useCallback(fn, deps) mengembalikan function yang sama selama dependency tidak berubah. Pasangan ideal: React.memo + useCallback.
useMemo: menyimpan hasil perhitungan mahal
const terurut = useMemo(
() => [...produk].sort((a, b) => a.harga - b.harga),
[produk]
);
Dihitung ulang hanya saat produk berubah. Juga berguna untuk menjaga referensi object/array agar tidak memicu render ulang anak yang di-memo.
Rangkuman alat
| Alat | Menyimpan | Kapan |
|---|---|---|
React.memo(Komponen) | hasil render | props sering sama |
useCallback(fn, deps) | function | dikirim sebagai props ke komponen ter-memo |
useMemo(() => nilai, deps) | nilai hasil hitung | perhitungan mahal / referensi stabil |
Teknik lain yang sering lebih efektif
- Pindahkan state lebih dekat ke komponen yang memakainya (agar sedikit komponen yang dirender ulang).
- Pisahkan komponen yang berubah cepat dari yang statis.
- Virtualisasi (react-window) untuk daftar sangat panjang.
- Code splitting dengan
React.lazydanSuspense.
Jangan berlebihan
memo, useMemo, dan useCallback punya biaya (memori dan kompleksitas). Pakai secukupnya, di titik yang terbukti bermasalah.