Episode ini membedah model store Zustand yang berisi state dan action dalam satu object, mekanisme subscribe/notify di balik layar, tiga API inti useStore, setState, dan subscribe, serta konsep selector, transient updates, dan vanilla store.

Setelah memahami sejarah, saatnya membedah mesin Zustand. Episode 2 menjelaskan model store, cara kerja subscribe/notify di balik layar, dan tiga API inti yang akan kalian gunakan di setiap episode berikutnya. Kalian tidak perlu menguasai implementasi internalnya secara sempurna, tapi memahami mental model ini akan menyelamatkan kalian dari bug yang membingungkan.
Kita mulai dari model store yang sederhana, lalu masuk ke mekanisme publikasi-subskripsi yang membuat re-render selektif mungkin terjadi, dan menutup dengan tiga API inti plus dua konsep kunci: selector dan transient updates.
Zustand memakai satu object store yang menampung dua hal sekaligus: state dan action. Tidak ada pemisahan file reducer, tidak ada action types terpisah. Kalian mendefinisikan keduanya dalam satu panggilan create():
import { create } from 'zustand'
type BearState = {
bears: number
addBear: () => void
}
export const useBearStore = create<BearState>((set) => ({
bears: 0,
addBear: () => set((s) => ({ bears: s.bears + 1 })),
}))Perhatikan create((set) => ...): argumen set adalah fungsi untuk memperbarui state, dan object yang dikembalikan menjadi isi store. State dan action hidup berdampingan dalam satu object — inilah yang membuat Zustand begitu ringkas.
Yang paling membedakan Zustand dari Context dan Redux: create() mengembalikan sebuah hook, bukan komponen Provider. Kalian langsung memanggilnya di komponen:
function BearCounter() {
const bears = useBearStore((s) => s.bears)
return <h1>{bears} bear</h1>
}Karena useBearStore adalah hook, tidak ada <Provider> yang membungkus aplikasi. useBearStore((s) => s.bears) adalah cara membaca state dengan selector — komponen subscribe ke slice tertentu, bukan ke seluruh store.
Zustand adalah mesin subscribe/notify: store menyimpan daftar listener, dan ketika state berubah, store memberitahu semua listener yang nilai selectornya ikut berubah. Ini pola yang sama dengan event emitter, di mana komponen berperan sebagai subscriber.
Setiap set() menghasilkan state baru. Zustand membandingkan hasil selector setiap listener dengan strict equality (===). Hanya listener yang hasil selectornya berbeda yang di-notify — inilah asal re-render selektif.
useBearStore.setState({ bears: 5 })
const current = useBearStore.getState()useBearStore.setState({ bears: 5 }) memperbarui state dan memicu notifikasi; useBearStore.getState() membaca state terkini tanpa subscribe. Kedua API ini bisa dipakai di luar komponen — misalnya dari event handler atau logika non-React.
Selector adalah fungsi yang menerima state utuh dan mengembalikan bagian yang dibutuhkan. Zustand menyimpan hasil selector terakhir; jika hasilnya sama persis secara referensi, komponen tidak di-render ulang. Karena itu, selector yang mengembalikan object baru setiap kali adalah jebakan — akan kita bahas di episode 5 dan 13.
Hook untuk membaca state di dalam React dengan subscribe otomatis. Bentuk lengkapnya adalah useStore(store, selector), dan store yang dihasilkan create() sudah ter-bind sehingga cukup memakai useBearStore(selector).
setState(partial) menerima object parsial atau fungsi updater; getState() membaca seluruh state pada saat itu juga. Keduanya tersedia di hook store dan store vanilla.
subscribe(listener) mendaftarkan listener yang dipanggil setiap state berubah:
const unsub = useBearStore.subscribe((state, prevState) => {
if (state.bears !== prevState.bears) {
console.log('bears berubah!')
}
})useBearStore.subscribe((state, prevState) => ...) menerima listener dengan state baru dan state lama, lalu mengembalikan fungsi unsub untuk berhenti subscribe. Untuk subscribe berbasis selector, kalian butuh middleware subscribeWithSelector — topik episode 5.
Ada kalanya state berubah sangat sering — misal posisi mouse atau progress download — dan tidak semua perubahan layak memicu render. Zustand mendukung transient updates: update lewat getState dan setState di luar React, atau subscribe manual ke ref tanpa re-render. Pola ini dioptimalkan di episode 13.
Core Zustand tidak bergantung pada React. createStore dari zustand/vanilla menghasilkan store murni yang sama, minus hook:
import { createStore } from 'zustand/vanilla'
const store = createStore((set) => ({
count: 0,
inc: () => set((s) => ({ count: s.count + 1 })),
}))
store.getState().inc()createStore((set) => ...) menghasilkan object dengan getState, setState, dan subscribe yang bisa dipakai di Node.js, worker, atau event bus. Di React, store ini dihubungkan lewat useStore — detail lengkap di episode 17.
Episode 2 memberi kalian mental model inti Zustand: satu store berisi state dan action, dibuat dengan create() yang mengembalikan hook tanpa Provider, bekerja di atas pola subscribe/notify dengan strict equality, dan mengekspos tiga API inti useStore, setState, serta subscribe.
Inti yang harus dibawa pulang:
Di episode 3 selanjutnya kita mulai praktik: setup, instalasi, dan store pertama — membuat project React, menginstall zustand, menyusun struktur folder stores, dan menulis store counter yang dipakai langsung di komponen. Siapkan terminal kalian!