Performance profiling di React.js adalah proses mengukur bagian mana yang lambat, kenapa lambat, dan optimisasi apa yang benar-benar memberi dampak. Fokusnya bukan membuat semua komponen “diproteksi” dengan memo, tetapi menemukan sumber biaya render yang paling mahal lalu memperbaikinya secara selektif.
Topik ini biasanya mencakup:
profiling render untuk melihat komponen yang sering atau lama dirender
useTransition untuk menurunkan prioritas update yang tidak harus terasa instan
useDeferredValue untuk menunda konsumsi nilai yang mahal agar UI tetap responsif
memoization heuristics untuk menentukan kapan React.memo, useMemo, dan useCallback layak dipakai
reducing render cost untuk menekan jumlah kerja per render, bukan sekadar mengurangi jumlah render
Kapan optimisasi dilakukan
Optimisasi performa dilakukan setelah ada bukti biaya nyata, bukan karena intuisi semata.
Pakai optimisasi kalau ada tanda seperti:
input terasa lag saat mengetik
scroll atau interaksi terasa patah-patah
render memakan waktu panjang di komponen tertentu
daftar besar sering rerender tanpa perubahan yang relevan
ada efek berantai dari state yang terlalu tinggi di tree
data derivatif dihitung ulang terlalu sering
Jangan mulai dari optimisasi kalau:
aplikasi belum terasa lambat
belum ada baseline pengukuran
masalahnya sebenarnya di network, data fetching, atau layout thrashing
komponen masih kecil dan sederhana
Aturan praktisnya begini:
ukur dulu
temukan bottleneck
ubah satu hal
ukur ulang
simpan hanya perubahan yang terbukti membantu
Cara kerja profiling
Profiling dipakai untuk menjawab tiga pertanyaan:
Apa yang dirender?
Berapa lama waktu render-nya?
Apa pemicunya?
Di React DevTools Profiler, kamu biasanya melihat:
commit yang terjadi saat UI berubah
komponen yang ikut rerender
durasi render dan commit
apakah update berasal dari props, state, atau context
Yang dicari bukan sekadar “komponen ini rerender”, karena rerender itu normal. Yang dicari adalah:
rerender yang mahal
rerender yang tidak perlu
rerender yang muncul berulang saat interaksi sederhana
Alur kerja yang sehat
Loading diagram...
useTransition
useTransition dipakai untuk menandai update yang tidak harus terasa instan. React akan memberi prioritas lebih rendah pada update tersebut, sehingga interaksi utama tetap responsif.
Gunakan saat:
ada input yang harus tetap cepat meskipun update berikutnya mahal
UI perlu menampilkan hasil filter, navigasi internal, atau perubahan view yang berat
ada transisi state yang bisa ditunda tanpa merusak pengalaman pengguna
saat pengguna harus tetap bisa mengetik atau klik tanpa delay
saat update berat bisa tampil sedikit terlambat
saat kamu ingin memisahkan urgent update dari non-urgent update
Batasan penting
useTransition bukan alat untuk mempercepat komputasi. Dia hanya mengatur prioritas. Kalau bottleneck-nya adalah algoritma mahal, kamu tetap perlu memperbaiki komputasi, caching, atau struktur data.
useDeferredValue
useDeferredValue dipakai ketika kamu ingin mengonsumsi nilai terbaru dengan sedikit penundaan agar bagian UI yang mahal tidak ikut memblokir interaksi utama.
Gunakan saat:
satu nilai input dipakai untuk komponen mahal, seperti daftar besar atau visualisasi kompleks
kamu ingin input tetap responsif sementara hasil turunan menyusul
ada perbedaan antara nilai yang sedang diketik dan nilai yang dipakai untuk render berat
saat update ke child tree mahal dan tidak perlu mengikuti input secara instan
saat kamu ingin menjaga typing tetap halus
saat sebagian UI boleh sedikit tertinggal dari state utama
Batasan penting
useDeferredValue bukan debounce. Ia tidak mengatur delay waktu secara eksplisit, dan bukan pengganti throttling/debouncing untuk kasus jaringan atau event burst. Ia lebih cocok untuk menunda render turunan, bukan menunda sumber event.
Memoization heuristics
Memoization berguna, tapi tidak gratis. Setiap memo punya biaya:
perbandingan dependency
penyimpanan nilai cache
kompleksitas mental saat debugging
Karena itu, heuristiknya harus jelas.
Pakai memoization kalau:
kalkulasi derivatif mahal dan inputnya relatif stabil
referensi function atau object memicu rerender yang tidak perlu
komponen child berat dan props-nya sering sama
kamu sudah melihat bottleneck nyata di profiler
Jangan pakai memoization kalau:
komponen ringan dan rerender-nya murah
nilai cached jarang dipakai ulang
optimisasi menambah kompleksitas tanpa bukti manfaat
dependency list sulit dijaga sehingga rawan stale value
Heuristik yang aman
Mulai dari pembatasan scope state, bukan memo
Ukur cost render, baru pilih memo yang tepat
Stabilkan referensi hanya jika referensi itu benar-benar memicu rerender mahal
Memoisasi data derivatif, bukan semua hal
Pertahankan kode mudah dibaca; performa yang sulit dipahami sering kalah oleh maintenance cost