Lesson 16 / 25
Creating a Store
State and actions together.
create returns a hook
create from zustand takes a function (set, get) => ({ ...state, ...actions }) and returns a React hook. Components call the hook with a selector to read state. set merges a partial object into state (a shallow merge at the top level), or takes an updater function set((state) => partial). get reads current state inside actions. No Provider is required because the store lives in module scope. In TypeScript, write create<State>()(...) with the extra parentheses so middleware types infer correctly.
A store is just a hook
Zustand creates small stores as hooks with no Provider and very little ceremony.
A counter and cart store
store.ts and a component.
import { create } from 'zustand';
type CartState = {
items: { id: string; qty: number }[];
add: (id: string) => void;
clear: () => void;
};
export const useCart = create<CartState>()((set) => ({
items: [],
add: (id) =>
set((state) => {
const hit = state.items.find((i) => i.id === id);
return {
items: hit
? state.items.map((i) => (i.id === id ? { ...i, qty: i.qty + 1 } : i))
: [...state.items, { id, qty: 1 }],
};
}),
clear: () => set({ items: [] }),
}));
function CartCount() {
const count = useCart((s) => s.items.length);
return <span>{count}</span>;
}A shared whiteboard
Anyone in the office can glance at one corner of the whiteboard (a selector) or write on it with the agreed marker (an action). No reception desk (Provider) is needed to get in.
Quick check: What does set({ items: [] }) do in Zustand?
- Deep-merges every nested object
- Replaces the whole state with { items: [] }
- Shallow-merges items into the existing state
- Throws because set needs a function
Answer
Shallow-merges items into the existing state — set merges at the top level unless you pass replace = true.