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.

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 adalah store paling dasar. Ia menyimpan nilai dan menyediakan method untuk membacanya secara reaktif:
import { writable } from "svelte/store"
export const count = writable(0)Di dalam komponen, prefix $ membuat store bisa dibaca dan di-update secara langsung:
<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 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:
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 menghitung nilai baru dari satu atau lebih store. Setiap kali store sumber berubah, nilai turunan ikut diperbarui:
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 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:
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.
Di luar komponen — misalnya di modul atau fungsi — kalian subscribe manual dengan .subscribe(callback) yang mengembalikan fungsi unsubscribe:
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.
Store bisa dibaca dengan prefix $ di dalam statement reaktif maupun runes:
<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.
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.
Untuk state yang hanya dipakai satu komponen, $state adalah pilihan paling sederhana. Tidak ada subscription, tidak ada indirection:
<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.
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.
Inti yang harus dibawa pulang:
writable untuk state yang bisa diubah, readable untuk nilai tetap, derived untuk nilai turunan.$ membuat store reaktif di komponen; .subscribe() manual untuk kode non-komponen.$.$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!