Zustand
Zustand: a tiny, hook-based state library for React. The default choice for client state in 2026.
React — Zustand
EXAMPLE
// Install: npm install zustand
import { create } from 'zustand';
// ===== Define a store =====
const useCounter = create((set, get) => ({
count: 0,
inc: () => set((s) => ({ count: s.count + 1 })),
reset: () => set({ count: 0 }),
doubleIt: () => set((s) => ({ count: get().count * 2 })),
}));
// ===== Use it =====
function Counter() {
const count = useCounter((s) => s.count);
const inc = useCounter((s) => s.inc);
return <button onClick={inc}>{count}</button>;
}
// Selectors prevent re-renders when unrelated state changes.
// ===== TypeScript =====
interface CartStore {
items: Item[];
add: (item: Item) => void;
remove: (id: number) => void;
}
const useCart = create<CartStore>()((set) => ({
items: [],
add: (item) => set((s) => ({ items: [...s.items, item] })),
remove: (id) => set((s) => ({ items: s.items.filter(i => i.id !== id) })),
}));
// ===== Middleware =====
import { devtools, persist } from 'zustand/middleware';
const useStore = create(
devtools(
persist(
(set) => ({ theme: 'light', setTheme: (t) => set({ theme: t }) }),
{ name: 'app-storage' }
)
)
);
// ===== Patterns =====
// - Slice pattern: split big stores into composable slices
// - Selectors with shallow compare for object selectors
// - Subscribe outside React with useStore.subscribe()
// - Default export for global single-instance stores
// ===== Pitfalls =====
// - Selecting whole state -> re-renders on every change
// - Using Zustand for server state (use TanStack Query)
// - Mutating state directly (use set() always)
Why it matters
Zustand: tiny, fast, hook-based store with middleware (persist, devtools, immer). Slice with selectors, persist with localStorage, debug with devtools. The default choice for cross-tree client state in 2026.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
import { create } from 'zustand';
const useStore = create((set) => ({
count: 0,
inc: () => set((s) => ({ count: s.count + 1 })),
}));
Try it Yourself »
Discussion
Loading…