Careeroza
Zustand
A Tiny Store
Zustand is a small (about 1 KB) state library popular in Next.js apps. No provider needed; components subscribe to just the slice they use.
Example
npm install zustandExample output
added 1 package in 2s
// stores/cart.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
type CartItem = { productId: number; name: string; price: number; qty: number };
type CartState = {
items: CartItem[];
add: (item: Omit<CartItem, 'qty'>) => void;
remove: (productId: number) => void;
};
export const useCartStore = create<CartState>()(
persist(
(set) => ({
items: [],
add: (item) =>
set((s) => {
const found = s.items.find((i) => i.productId === item.productId);
return {
items: found
? s.items.map((i) => (i.productId === item.productId ? { ...i, qty: i.qty + 1 } : i))
: [...s.items, { ...item, qty: 1 }],
};
}),
remove: (id) => set((s) => ({ items: s.items.filter((i) => i.productId !== id) })),
}),
{ name: 'shopease-cart' }, // saved in localStorage
),
);'use client';
import { useCartStore } from '@/stores/cart';
export function CartCount() {
const count = useCartStore((s) => s.items.reduce((n, i) => n + i.qty, 0)); // re-renders only when count changes
return <span>{count}</span>;
}How a Store Works
Example
The core of Zustand in 20 lines: state, set, and subscribers that get notified:
type Listener<T> = (state: T, prev: T) => void;
function createStore<T>(init: (set: (fn: (s: T) => Partial<T>) => void) => T) {
let state: T;
const listeners = new Set<Listener<T>>();
const set = (fn: (s: T) => Partial<T>) => {
const prev = state;
state = { ...state, ...fn(state) };
listeners.forEach((l) => l(state, prev));
};
state = init(set);
return { get: () => state, subscribe: (l: Listener<T>) => (listeners.add(l), () => listeners.delete(l)) };
}
type Cart = { items: string[]; add: (name: string) => void };
const store = createStore<Cart>((set) => ({
items: [],
add: (name) => set((s) => ({ items: [...s.items, name] })),
}));
const unsubscribe = store.subscribe((s, prev) => console.log('badge:', prev.items.length, '->', s.items.length));
store.get().add('Clean Code');
store.get().add('USB-C Cable');
unsubscribe();
store.get().add('Notebook');
console.log('items:', store.get().items.join(', '));Output
badge: 0 -> 1 badge: 1 -> 2 items: Clean Code, USB-C Cable, Notebook
SSR Caution
Note: A module-level store is shared by all users on the server. Only read/write it in Client Components (or create one store per request through a provider). Never put user data in a global server variable.