Episode ini mempraktikkan persiapan project: membuat project React, menginstall zustand, menyusun struktur folder stores, dan menulis store counter pertama. Kalian juga belajar pola membaca state via selector serta batasan destructuring store utuh.

Teori saja tidak cukup — di episode 3 kalian akan membuat project nyata dan menulis store pertama. Kita akan menyusun project React dengan Vite, menginstall Zustand, membangun struktur folder stores, lalu menulis store counter yang berfungsi penuh. Dari sini, seluruh episode berikutnya akan memakai pola yang sama.
Fokus episode ini adalah kebiasaan: struktur folder yang rapi, selector yang tepat, dan menghindari jebakan umum pemula. Kalian akan membawa pola ini ke project production nanti di episode 21.
Jika kalian belum menjalankan episode 0, siapkan project dulu:
npm create vite@latest belajar-zustand -- --template react-ts
cd belajar-zustand
npm install
npm i zustandPerintah npm i zustand menambahkan library inti. Pastikan package.json menampilkan versi 5.x untuk zustand — jika masih 4.x, jalankan npm i zustand@latest untuk menaikkan versinya.
Satu keputusan arsitektur sejak awal: semua store diletakkan di src/stores/, satu file per store. Aturan ini membuat tim kalian tahu persis ke mana mencari state.
src/
├── components/
├── pages/
└── stores/
├── counter.ts
└── (store lain di sini)Buat folder src/stores/ sekarang. Konvensi penamaan file store dengan huruf kecil di project ini, dan setiap store di-export sebagai hook berawalan use.
Ketik kode berikut di src/stores/counter.ts:
import { create } from 'zustand'
type CounterState = {
count: number
increment: () => void
decrement: () => void
reset: () => void
}
export const useCounter = create<CounterState>((set) => ({
count: 0,
increment: () => set((s) => ({ count: s.count + 1 })),
decrement: () => set((s) => ({ count: s.count - 1 })),
reset: () => set({ count: 0 }),
}))set((s) => ({ count: s.count + 1 })) memakai fungsi updater yang menerima state terkini. set({ count: 0 }) memakai object langsung. Kedua bentuk ini sah — detail perbedaannya kita bedah di episode 4.
Buka src/App.tsx dan gunakan store tersebut:
import { useCounter } from './stores/counter'
export default function App() {
const count = useCounter((s) => s.count)
const increment = useCounter((s) => s.increment)
const decrement = useCounter((s) => s.decrement)
const reset = useCounter((s) => s.reset)
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={increment}>Tambah</button>
<button onClick={decrement}>Kurang</button>
<button onClick={reset}>Reset</button>
</div>
)
}useCounter((s) => s.count) membaca state; useCounter((s) => s.increment) mengambil fungsi action. Keduanya dipanggil sebagai hook terpisah agar setiap pemanggilan hanya subscribe ke satu slice.
Gunakan satu useStore per slice, seperti di atas. Alternatif yang lebih ringkas adalah memakai useShallow untuk beberapa slice dalam satu object — akan kita bahas di episode 5.
Jebakan paling umum pemula adalah mengembalikan seluruh store dari selector:
// BURUK: seluruh store, memicu re-render di setiap perubahan
const counter = useCounter()
const { count, increment } = counterPola di atas menyebabkan komponen subscribe ke seluruh store, sehingga re-render selektif hilang. useCounter() tanpa selector adalah pintu menuju masalah performa yang kita bahas di episode 13.
Jalankan dev server:
npm run devBuka http://localhost:5173 — tombol Tambah, Kurang, dan Reset harus bekerja tanpa reload. Jika ya, store pertama kalian sudah hidup.
Pola yang sudah kalian terapkan di episode 3:
src/stores/, satu file per store.useXxx hasil create().useCounter((s) => s.count).useCounter((s) => s.increment).Kebiasaan kecil ini menentukan kualitas arsitektur state kalian di project besar.
Episode 3 menyelesaikan fondasi praktis: project Vite dengan zustand terinstall, struktur folder src/stores/, store counter ber-typed, dan komponen yang memakainya dengan selector per slice. Kalian juga sudah mengenali pola yang harus dihindari — destructuring store utuh.
Inti yang harus dibawa pulang:
src/stores/ dan ekspor sebagai hook berawalan use.npm i zustand cukup untuk mulai; verifikasi versi 5.x di package.json.set menerima fungsi updater atau object langsung.npm run dev untuk memverifikasi store bekerja di browser.Di episode 4 selanjutnya kita akan membedah API create(), set, dan get — anatomi store secara lengkap, dua bentuk set, peran get untuk membaca state terkini, serta pola update yang benar dengan immutability. Store pertama kalian baru satu dari sekian banyak pola.