Belajar Svelte - Stores & State Management
Episode 6 of 24

Belajar Svelte - Stores & State Management

Episode ini membedah state management di Svelte: writable, readable, dan derived stores, custom stores dengan method sendiri, mekanisme subscription, serta integrasi store dengan reactive statements dan lifecycle. Kalian juga belajar kapan memakai store dibanding runes.

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

Pendahuluan

Di episode 5 kalian belajar berbagi data antar komponen lewat props dan event. Itu cukup untuk komunikasi langsung antara parent dan child. Tapi bagaimana jika dua komponen yang jauh — misalnya navbar dan halaman pengaturan — harus membaca state yang sama? Melempar props berlapis-lapis akan membuat kode berantakan. Di sinilah store mengambil peran.

Store adalah objek reaktif yang bisa di-subscribe dari mana saja. Svelte menyediakan tiga tipe dasar: writable untuk state yang bisa diubah, readable untuk nilai yang hanya bisa dibaca, dan derived untuk nilai yang dihitung dari store lain. Ditambah kemampuan menulis custom store, kalian bisa membangun pola state management yang sesuai kebutuhan aplikasi.

Episode ini membahas ketiga tipe store, custom store, mekanisme subscription, dan integrasinya dengan reactive statements serta lifecycle. Di akhir episode, kalian tahu persis kapan memakai store dan kapan cukup memakai runes $state.

Writable, Readable, dan Derived Store

Writable Store

writable adalah store paling dasar. Ia menyimpan nilai dan menyediakan method untuk membacanya secara reaktif:

JSMembuat writable store
import { writable } from "svelte/store"
 
export const count = writable(0)

Di dalam komponen, prefix $ membuat store bisa dibaca dan di-update secara langsung:

Menggunakan store di komponen
<script>
  import { count } from "../lib/stores.js"
 
  function tambah() {
    count.update((n) => n + 1)
  }
</script>
 
<button onclick={tambah}>Klik {$count}</button>

$count adalah nilai store saat ini — Svelte meng-compile-nya menjadi subscription otomatis. count.update((n) => n + 1) mengubah nilai dengan fungsi transformasi. .set(value) menimpa nilai sepenuhnya.

Readable Store

readable dipakai untuk nilai yang tidak bisa diubah dari luar — misalnya timer, clock, atau status yang diisi sekali. Argumen kedua adalah fungsi yang menerima set dan berjalan saat subscriber pertama datang:

JSReadable store dengan timer
import { readable } from "svelte/store"
 
export const jam = readable(new Date(), (set) => {
  const id = setInterval(() => set(new Date()), 1000)
  return () => clearInterval(id)
})

readable(nilaiAwal, (set) => ...) mengisi nilai lewat set. Fungsi yang dikembalikan dipanggil saat subscriber terakhir pergi — tempat membersihkan interval. Inilah integrasi store dengan lifecycle: subscription dan cleanup diatur Svelte secara otomatis.

Derived Store

derived menghitung nilai baru dari satu atau lebih store. Setiap kali store sumber berubah, nilai turunan ikut diperbarui:

JSDerived store dari dua sumber
import { writable, derived } from "svelte/store"
 
export const harga = writable(1000)
export const qty = writable(2)
 
export const total = derived([harga, qty], ([h, q]) => h * q)

derived([harga, qty], ([h, q]) => h * q) menerima array store sebagai sumber dan fungsi untuk menghitung hasilnya. total hanya diperbarui saat harga atau qty berubah — tidak ada perhitungan sia-sia.

Custom Store dan Subscription

Membuat Custom Store

Custom store adalah objek apa pun yang memiliki method subscribe. Pola paling umum: membungkus writable dan mengekspos method yang sudah disesuaikan. Ini menyembunyikan detail internal dan mencegah modifikasi asal:

JSCustom store untuk keranjang
import { writable } from "svelte/store"
 
function buatKeranjang() {
  const { subscribe, update } = writable([])
 
  return {
    subscribe,
    tambah(item) {
      update((items) => [...items, item])
    },
    hapus(id) {
      update((items) => items.filter((i) => i.id !== id))
    },
    reset() {
      update(() => [])
    },
  }
}
 
export const keranjang = buatKeranjang()

buatKeranjang() mengembalikan object dengan subscribe yang diambil dari writable internal, plus method tambah, hapus, dan reset. Komponen tidak bisa menyentuh array mentah secara langsung — semua perubahan lewat method. Ini contoh pola facade yang membuat state management aman.

Subscription Manual

Di luar komponen — misalnya di modul atau fungsi — kalian subscribe manual dengan .subscribe(callback) yang mengembalikan fungsi unsubscribe:

JSSubscribe manual
import { count } from "../lib/stores.js"
 
const unsubscribe = count.subscribe((nilai) => {
  console.log("Nilai baru:", nilai)
})
 
unsubscribe()

count.subscribe((nilai) => ...) menjalankan callback setiap kali nilai berubah dan langsung sekali saat subscribe. Fungsi yang dikembalikan adalah unsubscribe — wajib dipanggil saat tidak lagi butuh, atau akan terjadi kebocoran memori.

Integrasi dengan Reactive Statements dan Lifecycle

Store dalam Reactive Statements

Store bisa dibaca dengan prefix $ di dalam statement reaktif maupun runes:

Store dan derived di komponen
<script>
  import { keranjang } from "../lib/keranjang.js"
</script>
 
<p>Total item: {$keranjang.length}</p>

$keranjang.length dibaca secara reaktif di markup. Saat keranjang berubah, teks diperbarui tanpa menulis kode subscription. Kombinasi store dengan $derived juga umum untuk menghitung nilai tampilan di level komponen.

Store dan Lifecycle Hook

Saat store dikombinasikan dengan onMount dan onDestroy, pastikan subscription manual selalu dibersihkan.

Prefix $ di komponen otomatis mengurus unsubscribe saat komponen dihancurkan. Namun jika kalian memanggil .subscribe() manual, simpan fungsi unsubscribe dan panggil di onDestroy — kebiasaan yang mencegah kebocoran memori di aplikasi besar.

Kapan Memakai Store vs Runes

Runes untuk State Lokal

Untuk state yang hanya dipakai satu komponen, $state adalah pilihan paling sederhana. Tidak ada subscription, tidak ada indirection:

State lokal dengan runes
<script>
  let buka = $state(false)
</script>
 
<button onclick={() => (buka = !buka)}>
  {buka ? "Tutup" : "Buka"} panel
</button>

let buka = $state(false) cukup untuk state yang tidak keluar dari komponen. Menambahkan store pada state seperti ini justru menambah kompleksitas tanpa manfaat.

Store untuk State Bersama

Gunakan store saat state dibaca atau diubah oleh banyak komponen yang tidak terhubung langsung: user session, keranjang belanja, preferensi tema, notifikasi. Store juga cocok untuk data yang diambil server dan dipakai lintas halaman.

Prinsipnya sederhana: mulai dengan $state, naik ke store saat state mulai dibagi antar banyak komponen. Episodes berikutnya memakai pola ini terus-menerus, mulai dari auth hingga pengaturan tema.

Penutup

Inti yang harus dibawa pulang:

  • writable untuk state yang bisa diubah, readable untuk nilai tetap, derived untuk nilai turunan.
  • Custom store membungkus writable dan mengekspos method yang aman dan deskriptif.
  • Prefix $ membuat store reaktif di komponen; .subscribe() manual untuk kode non-komponen.
  • Selalu panggil unsubscribe untuk subscription manual agar tidak bocor.
  • Integrasi store dengan lifecycle dikelola otomatis lewat prefix $.
  • Mulai dengan runes $state untuk state lokal; gunakan store saat state dibagi lintas komponen.

Di episode 7 selanjutnya kita akan membahas transitions dan animations — motion directives transition:, animate:, in:, dan out:, serta custom animation dengan tweened dan spring. Store akan berperan sebagai sumber nilai yang di-animasi. Sampai jumpa di episode berikutnya!