Episode ini membahas middleware immer untuk memperbarui state nested secara mutable-tapi-immutable lewat fungsi draft, perbandingannya dengan manual spread, kapan memakai immer versus spread, serta trade-off performa keduanya.

State aplikasi nyata tidak pernah sederhana — object bersarang, array dalam object, dan struktur yang saling terkait. Di episode 4 kita belajar memperbarui state nested dengan spread berlapis yang rawan salah. Episode 9 memperkenalkan immer, middleware yang membiarkan kalian menulis mutasi langsung pada draft dan tetap menghasilkan state immutable.
Kita akan membahas cara kerja draft, pola penulisan yang benar, kapan immer mengungguli spread manual, dan kapan sebaiknya tidak memakainya.
Impor dan bungkus store dengan immer:
import { create } from 'zustand'
import { immer } from 'zustand/middleware/immer'
interface ProfileState {
profile: {
name: string
address: { city: string; country: string }
}
setCity: (city: string) => void
}
export const useProfile = create<ProfileState>()(
immer((set) => ({
profile: { name: 'Arman', address: { city: 'Bandung', country: 'ID' } },
setCity: (city) =>
set((state) => {
state.profile.address.city = city
}),
})),
)Di dalam set((state) => ...), parameter state adalah draft. Kalian memutasinya langsung — state.profile.address.city = city — dan immer menyalin hanya bagian yang berubah secara otomatis. Hasil akhirnya tetap immutable.
Draft bekerja seperti struktur asli: kalian bisa memodifikasi properti, push ke array, atau hapus elemen, semuanya seolah mutasi biasa:
addTag: (tag) =>
set((state) => {
state.tags.push(tag)
}),
removeTag: (tag) =>
set((state) => {
const idx = state.tags.indexOf(tag)
if (idx !== -1) state.tags.splice(idx, 1)
}),state.tags.push(tag) dan state.tags.splice(idx, 1) adalah mutasi langsung yang aman — immer mencatatnya sebagai perubahan struktural dan menghasilkan state baru. Kode jadi jauh lebih pendek dibanding spread berlapis.
Untuk satu level, keduanya mirip. Perbedaannya mencolok saat struktur dalam:
// Spread manual, empat level
set((s) => ({
settings: {
...s.settings,
theme: {
...s.settings.theme,
accent: 'teal',
},
},
}))
// Immer, satu mutasi
set((s) => {
s.settings.theme.accent = 'teal'
})set((s) => { s.settings.theme.accent = 'teal' }) menggantikan empat lapis spread dengan satu baris mutasi draft. Semakin dalam struktur, semakin besar keuntungan keterbacaan immer.
Kesalahan paling umum spread manual: lupa menyebar satu level, sehingga object lama masih ter-referensi dan perubahan tidak terdeteksi. Immer menghilangkan kelas error ini karena penyalinan ditangani otomatis.
Immer bukan tanpa biaya. Setiap draft membutuhkan proxy dan proses copy-on-write, sehingga ada overhead kecil per update — sangat terasa saat state sangat besar dan update berfrekuensi tinggi, misalnya editor teks atau simulasi realtime.
Update kecil + state kecil → spread manual sama cepat
Update dalam + state dalam → immer lebih produktif
Update per frame, state besar → pertimbangkan spreadUntuk update per frame (animasi, drag), hindari immer. Untuk update user-triggered yang jarang dan state-nya dalam, immer adalah pilihan yang sangat nyaman.
Immer membiarkan update yang tidak mengubah apa pun — misalnya menetapkan nilai yang sama — dan hasilnya tetap mengembalikan referensi yang sama, sehingga tidak memicu re-render. Ini perilaku yang diinginkan.
Gunakan immer ketika:
Hindari immer ketika:
npm i immernpm i immer menginstall dependensi yang dibutuhkan middleware. Zustand mengekspos immer dari zustand/middleware/immer — versi package immer dipakai secara otomatis dari dependensi project kalian.
Episode 9 menunjukkan kekuatan immer: update nested yang ditulis secara mutable-tapi-immutable lewat draft, kode yang jauh lebih pendek dari spread berlapis, dan pemilihan kapan immer layak dipakai berdasarkan kompleksitas state serta frekuensi update.
Inti yang harus dibawa pulang:
Di episode 10 selanjutnya kita akan membahas middleware: devtools dan redux — integrasi Redux DevTools dengan time-travel dan tracing action, konfigurasi nama store, serta middleware redux untuk pola reducer ala Redux di dalam Zustand.