Belajar Zustand - API create(), set & get
Episode 4 of 23

Belajar Zustand - API create(), set & get

Episode ini membedah anatomi create((set, get) => ...), dua bentuk set berupa object dan fungsi updater, serta peran get untuk membaca state terkini di dalam action. Kalian juga belajar pola update yang benar dengan spread dan immutability.

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

Pendahuluan

Di episode 3 kalian menulis store pertama tanpa menyadari kekuatan penuh yang dipegang set dan get. Episode 4 membedah anatomi create(): apa saja yang diterima fungsi initializer, dua bentuk set, kapan memakai get, dan mengapa immutability menjadi hukum yang tidak bisa ditawar.

Setelah episode ini, kalian akan menulis action yang kompleks — membaca state lain, memperbarui beberapa field sekaligus, dan menghindari bug referensi — dengan percaya diri.

Anatomi create()

Fungsi Initializer dan Dua Parameternya

create() menerima fungsi initializer yang dipanggil sekali saat store dibuat:

JScreate dengan set dan get
import { create } from 'zustand'
 
type CartState = {
  items: string[]
  addItem: (item: string) => void
  summary: () => number
}
 
export const useCart = create<CartState>((set, get) => ({
  items: [],
  addItem: (item) => set((s) => ({ items: [...s.items, item] })),
  summary: () => get().items.length,
}))

Parameter pertama set memperbarui state, parameter kedua get membaca state terkini. get().items.length di dalam summary membaca panjang array saat action dipanggil — bukan saat store dibuat.

create() Mengembalikan Hook

Hasil create() adalah hook yang punya properti statis: .getState(), .setState(), dan .subscribe(). Store dan hook jadi satu, tanpa konfigurasi terpisah — inilah yang membuat API Zustand terasa seperti satu kesatuan.

set: Dua Bentuk Update

Object Langsung

Bentuk pertama menerima object parsial yang di-merge ke state:

JSset dengan object langsung
reset: () => set({ count: 0, status: 'idle' })

set({ count: 0, status: 'idle' }) mengganti field count dan status sekaligus, sedangkan field lain dipertahankan. Bentuk ini tepat ketika nilai baru sudah tersedia dan tidak bergantung pada state lama.

Fungsi Updater

Bentuk kedua menerima fungsi yang menerima state terkini:

JSset dengan fungsi updater
increment: () => set((s) => ({ count: s.count + 1 }))

set((s) => ({ count: s.count + 1 })) aman dipanggil berkali-kali karena selalu membaca state terbaru. Jika beberapa set dipanggil beruntun, bentuk updater tidak akan kehilangan perubahan — beda dengan object langsung yang dihitung dari nilai lama.

get: Membaca State Terkini

get berguna ketika action butuh membaca state di luar field yang diubah, misalnya sebelum membuat keputusan:

JSget untuk membaca state lain
export const useAuth = create<AuthState>((set, get) => ({
  user: null,
  login: (user) => {
    const prev = get().user
    set({ user, lastLogin: prev ? prev.name : null })
  },
  isLoggedIn: () => get().user !== null,
}))
 
if (useAuth.getState().isLoggedIn()) {
  console.log('sudah login')
}

get().user di dalam action membaca state terbaru, dan useAuth.getState().isLoggedIn() memungkinkan pemanggilan dari luar komponen — misalnya dari utility atau router guard.

Pola Update yang Benar

Spread Manual untuk Object

Saat memperbarui state nested, kalian harus menyalin level yang diubah secara manual:

JSUpdate nested dengan spread
type ProfileState = {
  profile: { name: string; email: string }
  setEmail: (email: string) => void
}
 
export const useProfile = create<ProfileState>((set) => ({
  profile: { name: 'Arman', email: '' },
  setEmail: (email) =>
    set((s) => ({ profile: { ...s.profile, email } })),
}))

{ ...s.profile, email } membuat object profile baru sambil mempertahankan field lain. Memutasi s.profile.email = email tanpa salinan akan merusak deteksi perubahan — ini topik inti immer di episode 9.

Multiple Set dalam Satu Action

Panggil set beberapa kali dalam satu action jika langkah update berbeda, tapi ingat: setiap set memicu notifikasi.

JSBeberapa set dalam satu action
export const useForm = create<FormState>((set) => ({
  values: {},
  errors: {},
  submitStart: () => {
    set({ status: 'loading' })
    set({ errors: {} })
  },
}))

Untuk update yang bisa digabung, sebaiknya satu set saja dengan beberapa field. set({ status: 'loading', errors: {} }) lebih efisien daripada dua panggilan terpisah.

Immutability sebagai Hukum

Zustand mendeteksi perubahan lewat perbandingan referensi. Prinsipnya:

  • Jangan pernah memutasi state yang ada.
  • Selalu kembalikan object/array baru untuk bagian yang berubah.
  • Pertahankan referensi lama untuk bagian yang tidak berubah.
JSPola mutasi yang salah
// BURUK: mutasi langsung, tidak terdeteksi
set((s) => {
  s.user.name = 'Baru'
  return s
})

Kode di atas mengembalikan object yang sama, sehingga komponen tidak re-render. Selalu buat object baru seperti pola spread di atas, atau gunakan middleware immer dari episode 9 untuk menulisnya dengan aman.

Penutup

Episode 4 melengkapi senjata dasar kalian: create((set, get) => ...) membangun store, set memperbarui state dalam dua bentuk, get membaca state terkini, dan immutability menjaga deteksi perubahan tetap berfungsi.

Inti yang harus dibawa pulang:

  • create((set, get) => ...) menerima dua parameter yang bekerja di dalam action.
  • set dapat menerima object langsung atau fungsi updater.
  • Fungsi updater aman dipanggil beruntun karena selalu membaca state terbaru.
  • get membaca state terkini di dalam action untuk logika keputusan.
  • Selalu spread object/array yang berubah; jangan pernah mutasi.
  • Gabungkan update yang bersamaan dalam satu set untuk efisiensi.

Di episode 5 selanjutnya kita akan membahas selector dan subscription — memilih slice state agar re-render minimal, memakai useShallow untuk beberapa slice, dan subscribe manual dengan subscribeWithSelector untuk log, analitik, dan sinkronisasi non-React.