Reactjs Rendering Performance Memo Usememo Usecallback React Memo Key Stability
Selesai membaca dokumentasi ini?
Kembali ke rujukan utama React.js untuk melanjutkan topik lainnya.
Kembali ke rujukan utama React.js untuk melanjutkan topik lainnya.
Rendering performance di React adalah kemampuan aplikasi untuk memperbarui UI dengan efisien saat state, props, atau context berubah. Tujuannya bukan membuat React “tidak rerender sama sekali”, karena rerender itu normal. Tujuan yang benar adalah memastikan React hanya mengerjakan bagian yang memang perlu diubah, dan tidak membayar biaya tambahan untuk komponen, kalkulasi, atau daftar item yang sebenarnya bisa dipertahankan.
Topik ini biasanya menyentuh lima area yang sering dipakai bersamaan:
memo sebagai istilah umum untuk optimisasi yang menahan kerja ulanguseMemo untuk menyimpan hasil perhitunganuseCallback untuk menyimpan referensi fungsiReact.memo untuk mencegah child rerender kalau props-nya stabilkey untuk menjaga identity item saat daftar berubahKalau dipakai tepat, hasilnya UI terasa lebih responsif dan kerja render lebih terkontrol. Kalau dipakai asal, optimisasi justru menambah kompleksitas, bikin dependency berantakan, dan kadang tidak memberi manfaat sama sekali.
Pakai optimisasi ini kalau ada tanda yang jelas, misalnya:
Patokan yang sehat: optimisasi harus menjawab masalah yang terukur, bukan sekadar “supaya aman”.
Optimisasi rendering sering menjadi overkill kalau:
useMemo atau useCallback dipakai di mana-mana tanpa kebutuhan nyataDalam React, biaya membaca dan merawat kode juga biaya performa. Kalau optimisasi membuat komponen sulit dipahami, itu bisa jadi kerugian yang lebih besar daripada rerender yang sedang dihemat.
Yang perlu dipahami dari alur ini:
useMemo dan useCallback tidak menghentikan render; keduanya hanya membantu mempertahankan hasil atau referensi.React.memo bekerja di level child component, dengan membandingkan props.key memengaruhi bagaimana React mengenali identity item dalam list, bukan sekadar label.useMemouseMemo menyimpan hasil perhitungan agar React tidak menghitung ulang nilai itu pada setiap render, selama dependency belum berubah.
const visibleUsers = useMemo(() => {
return users.filter(user => user.name.includes(query));
}, [users, query]);Gunakan useMemo untuk:
Jangan pakai useMemo kalau:
useMemo adalah cache permanen. Padahal memo bisa dibuang React dalam kondisi tertentu.useMemo untuk setiap object literal kecil tanpa bukti kebutuhan.useCallbackuseCallback menyimpan referensi fungsi agar identitas function tetap stabil antar render selama dependency tidak berubah.
const handleSelect = useCallback((id) => {
setSelectedId(id);
}, []);Pakai useCallback kalau:
React.memouseEffect, useMemo, atau custom hookKalau fungsi hanya dipakai lokal di komponen yang sama dan tidak diteruskan ke child, useCallback sering tidak memberi keuntungan nyata.
useCallback untuk semua handler tanpa alasan.React.memoReact.memo membungkus component agar React dapat melewati rerender child jika props yang diterima dianggap sama.
const UserRow = React.memo(function UserRow({ user, onSelect }) {
return (
<li>
<button onClick={() => onSelect(user.id)}>{user.name}</button>
</li>
React.memo cocok untuk child component yang:
Jangan gunakan React.memo kalau:
React.memo otomatis ampuh. Kalau props mengandung object, array, atau function baru tiap render, memo sering gagal membantu.useMemo, useCallback, dan React.memoKetiga API ini sering dipakai bersama, tapi perannya berbeda:
useMemo menyimpan nilai hasil perhitunganuseCallback menyimpan referensi fungsiReact.memo mencegah child rerender bila props stabilPola umumnya begini:
useMemo.useCallback.React.memo.Kalau salah satu rantai ini putus, optimisasi lain bisa ikut tidak efektif.
List rendering adalah proses merender banyak item dari data array ke elemen UI.
{items.map(item => (
<ProductCard key={item.id} item={item} />
))}List sering menjadi sumber rerender mahal karena:
React.memo untuk item yang stabilmap kalau bisa dipindahkan atau distabilkanmap.key untuk list yang bisa berubah urutan.key adalah identitas stabil untuk item list. React memakainya untuk mencocokkan item lama dan baru saat daftar berubah.
Kalau key stabil, React bisa:
Kalau key tidak stabil, React bisa salah mengira item lama sebagai item baru. Akibatnya:
Pilih key yang:
id{todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}Hindari:
Math.random()// Hindari
{items.map((item, index) => (
<Row key={index} item={item} />
))}Object, array, dan function yang dibuat inline akan punya referensi baru setiap render.
<Child options={{ dense: true }} onClick={() => handleClick(id)} />Kalau Child memakai React.memo, props seperti ini bisa membuat memo gagal efektif.
Kalau state diletakkan di parent yang besar, satu perubahan kecil bisa memicu rerender subtree yang luas.
Filtering atau sorting yang sama sebaiknya tidak diulang berkali-kali di level komponen yang berbeda kalau hasilnya bisa dipusatkan.
Index key, random key, atau key yang berubah karena urutan data akan membuat React kehilangan identity item.
Custom comparison di React.memo yang terlalu dalam atau terlalu banyak operasi bisa lebih mahal daripada rerender biasa.
Mengubah banyak komponen menjadi memoized tanpa bukti sering berakhir pada kode yang lebih rumit tapi tidak lebih cepat.
import { memo, useCallback, useMemo, useState } from 'react';
const UserRow = memo(function UserRow({ user, onSelect }) {
return (
<li
Contoh ini masuk akal karena:
useMemouseCallbackReact.memokey memakai user.id, bukan indexPakai alur keputusan sederhana ini:
Pertanyaan paling penting bukan “bisa dioptimalkan atau tidak”, melainkan:
useMemo, useCallback, dan React.memo punya fungsi berbeda.useMemo untuk hasil perhitungan.useCallback untuk referensi fungsi.React.memo untuk child component yang props-nya stabil.key harus stabil dan berasal dari identity data.