Belajar Pinia - Performance & Reactivity Tuning
Episode 13 of 23

Belajar Pinia - Performance & Reactivity Tuning

State management yang besar bisa menjadi sumber re-render berlebihan. Episode ini membahas cara mengontrol re-render dengan storeToRefs dan state granular, memakai $subscribe dengan opsi detached, serta membatch banyak update dengan $patch untuk performa yang lebih baik.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Semakin besar aplikasi, semakin mudah store menjadi sumber re-render yang tidak perlu. Setiap field state yang berubah bisa memicu ulang komponen yang membacanya — dan jika seluruh komponen membaca seluruh store, satu perubahan kecil berujung render massal.

Episode 13 membahas tuning reactivity Pinia: mengontrol re-render dengan storeToRefs dan akses granular, memakai $subscribe dengan opsi detached, serta membatch update dengan $patch. Ini bukan mikro-optimasi — ini pola yang mencegah aplikasi melambat saat store tumbuh.

storeToRefs vs Akses Langsung

Perhatikan bagaimana cara membaca memengaruhi re-render:

JSAkses granular versus seluruh store
// Re-render saat field yang dipakai berubah
const { count, double } = storeToRefs(store)
 
// Potensi re-render lebih luas: template membaca banyak properti
const store = useCounterStore()

const { count, double } = storeToRefs(store) mengambil hanya field yang dibutuhkan, sehingga Vue hanya melacak dependency itu. Sebaliknya, memakai store utuh dan membaca banyak properti bisa menciptakan lebih banyak dependency — tidak salah, tetapi kurang presisi.

State Granular

Jangan menaruh seluruh data aplikasi di satu store besar. Pecah menjadi store kecil dan state yang spesifik:

JSGranular state per domain
// Buruk: satu state menampung banyak domain
state: () => ({ user: {}, cart: [], ui: { modal: null } })
 
// Lebih baik: terpisah per store
useAuthStore()  // user
useCartStore()  // cart
useUiStore()    // modal, sidebar

Dengan store terpisah, komponen yang hanya butuh cart tidak ikut terpengaruh saat ui berubah. Prinsip ini mengurangi re-render dan membuat dependency tracking lebih tajam.

$subscribe dengan Opsi detached

Secara default, $subscribe berhenti saat komponen yang mendaftarkannya dibongkar. Untuk subscriber yang hidup lebih lama, kirim { detached: true }:

JSSubscribe detached di komponen
store.$subscribe(
  (_mutation, state) => {
    saveToStorage(state)
  },
  { detached: true },
)

{ detached: true } membuat subscriber tetap aktif meskipun komponen sudah di-unmount. Gunakan untuk tugas jangka panjang seperti autosave. Jika tidak, biarkan default agar subscriber ikut dibersihkan dan tidak bocor.

Batching Update dengan $patch

Beberapa assignment berurutan memicu banyak pembaruan. $patch menggabungkannya menjadi satu:

JSBanyak update dalam satu patch
// Tiga pembaruan terpisah
store.firstName = 'Arman'
store.lastName = 'Dwi'
store.age = 26
 
// Satu patch
store.$patch({
  firstName: 'Arman',
  lastName: 'Dwi',
  age: 26,
})

store.$patch({ ... }) mengelompokkan perubahan sehingga subscriber dan DevTools hanya mencatat satu mutasi. Ini penting untuk sinkronisasi storage dan observability yang lebih efisien.

$subscribe vs watch

Pinia menyediakan dua jalan untuk memantau perubahan: $subscribe milik store dan watch milik Vue. Kapan memakai yang mana?

  • $subscribe hanya mendeteksi perubahan state setelah sukses dimutasi, dan { flush: 'sync' } bisa diatur agar callback berjalan sebelum komponen re-render. Cocok untuk sinkronisasi eksternal seperti storage atau analytics.
  • watch(store.$state, ...) memakai mekanisme watch Vue biasa, mendukung deep dan immediate, serta lebih mudah dibatalkan jika sumbernya adalah composable milik kalian sendiri.
JSMemantau state dengan watch
watch(
  () => store.$state.cart,
  (cart) => {
    console.log('cart berubah', cart)
  },
  { deep: true },
)

Untuk kasus sederhana, pilih yang paling sedikit memakai API eksternal: watch bila kalian sudah di dalam komponen dan butuh dependency tracking standar, $subscribe bila kalian bekerja dengan store secara langsung, misalnya di plugin atau saat membuat utility yang hidup di luar komponen.

Warning

Optimasi tidak dimulai dari mikro-patch. Mulailah dari struktur data: store kecil per domain dan akses granular. $patch dan detached adalah penyempurnaan setelah fondasi sudah benar.

Penutup

Episode 13 membekali kalian pola performance yang bisa langsung diterapkan. Kalian sekarang bisa mengontrol re-render dengan storeToRefs dan state granular, mengatur umur subscriber dengan detached, serta membatch update dengan $patch.

Inti yang harus dibawa pulang:

  • storeToRefs membatasi dependency tracking pada field yang dipakai.
  • Pecah state besar menjadi store per domain.
  • { detached: true } membuat $subscribe hidup lebih lama.
  • $patch menggabungkan banyak update menjadi satu mutasi.
  • Optimasi dimulai dari struktur store, bukan dari mikro-patch.
  • Ukur dampak dengan DevTools sebelum mengejar optimasi.

Di episode 14 selanjutnya kita akan membahas async server state dan integrasi lanjutan — Pinia Colada untuk fetching dan caching server state, menggabungkan store dengan Vue Router, serta integrasi dengan composables eksternal. Ini jembatan Pinia menuju arsitektur aplikasi modern.