| name | zustand |
| description | Zustand state management patterns including store creation, middleware, persistence, slices, and DevTools integration. |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
| graph | {"domains":["domain:web-development"],"specializations":["specialization:web-development"],"skillAreas":["skill-area:react-state-management","skill-area:application-state-management"],"roles":["role:frontend-engineer"],"topics":["topic:flux-pattern"]} |
Zustand Skill
Expert assistance for implementing Zustand state management with modern patterns and TypeScript.
Capabilities
- Create type-safe Zustand stores
- Implement middleware (persist, devtools, immer)
- Design store slices for modular state
- Optimize selectors for performance
- Handle async actions and subscriptions
- Integrate with React components efficiently
Usage
Invoke this skill when you need to:
- Set up lightweight global state
- Create stores with persistence
- Implement complex state with slices
- Optimize component re-renders with selectors
- Migrate from Redux or Context
Inputs
| Parameter | Type | Required | Description |
|---|
| storeName | string | Yes | Name of the store |
| stateShape | object | Yes | Initial state structure |
| actions | array | Yes | Store actions to create |
| middleware | array | No | Middleware to apply |
| persist | boolean | No | Enable persistence |
Configuration Example
{
"storeName": "useCartStore",
"stateShape": {
"items": [],
"total": 0
},
"actions": ["addItem", "removeItem", "clearCart"],
"middleware": ["devtools", "persist"],
"persist": true
}
Generated Patterns
Basic Store
import { create } from 'zustand';
interface CartItem {
id: string;
name: string;
price: number;
quantity: number;
}
interface CartStore {
items: CartItem[];
total: number;
addItem: (item: Omit<CartItem, 'quantity'>) => void;
removeItem: (id: string) => void;
updateQuantity: (id: string, quantity: number) => void;
clearCart: () => void;
}
export const useCartStore = create<CartStore>((set, get) => ({
items: [],
total: 0,
addItem: (item) =>
set(() => {
existingItem = state..( i. === item.);
(existingItem) {
{
: state..(
i. === item. ? { ...i, : i. + } : i
),
: state. + item.,
};
}
{
: [...state., { ...item, : }],
: state. + item.,
};
}),
:
( {
item = state..( i. === id);
{
: state..( i. !== id),
: state. - (item ? item. * item. : ),
};
}),
:
( {
item = state..( i. === id);
(!item) state;
diff = (quantity - item.) * item.;
{
: state..(
i. === id ? { ...i, quantity } : i
),
: state. + diff,
};
}),
: ({ : [], : }),
}));
Store with Middleware
import { create } from 'zustand';
import { devtools, persist, subscribeWithSelector } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
interface UserStore {
user: User | null;
preferences: Preferences;
setUser: (user: User) => void;
updatePreferences: (prefs: Partial<Preferences>) => void;
logout: () => void;
}
export const useUserStore = create<UserStore>()(
devtools(
persist(
subscribeWithSelector(
immer((set) => ({
user: null,
preferences: { theme: 'light', notifications: true },
setUser: (user) =>
set(() => {
state. = user;
}),
:
( {
.(state., prefs);
}),
:
( {
state. = ;
}),
}))
),
{
: ,
: ({ : state. }),
}
),
{ : }
)
);
Slice Pattern
import { create, StateCreator } from 'zustand';
interface AuthSlice {
isAuthenticated: boolean;
token: string | null;
login: (token: string) => void;
logout: () => void;
}
interface UISlice {
sidebarOpen: boolean;
theme: 'light' | 'dark';
toggleSidebar: () => void;
setTheme: (theme: 'light' | 'dark') => void;
}
type StoreState = AuthSlice & UISlice;
const createAuthSlice: StateCreator<StoreState, [], [], AuthSlice> = (set) => ({
isAuthenticated: false,
token: null,
login: (token) => set({ : , token }),
: ({ : , : }),
});
: <, [], [], > = ({
: ,
: ,
: ( ({ : !state. })),
: ({ theme }),
});
useAppStore = create<>()( ({
...(...a),
...(...a),
}));
Async Actions
import { create } from 'zustand';
interface DataStore {
data: Item[];
loading: boolean;
error: string | null;
fetchData: () => Promise<void>;
}
export const useDataStore = create<DataStore>((set, get) => ({
data: [],
loading: false,
error: null,
fetchData: async () => {
set({ loading: true, error: null });
try {
const response = await fetch('/api/data');
const data = await response.json();
set({ data, loading: false });
} catch (error) {
set({ error: (error as Error).message, loading: false });
}
},
}));
Selector Patterns
import { shallow } from 'zustand/shallow';
const { items, total } = useCartStore(
(state) => ({ items: state.items, total: state.total }),
shallow
);
const itemCount = useCartStore((state) =>
state.items.reduce((sum, item) => sum + item.quantity, 0)
);
Best Practices
- Use selectors to minimize re-renders
- Apply persist middleware for state that should survive refreshes
- Use immer for complex nested updates
- Split large stores into slices
- Keep actions colocated with state
Target Processes
- react-application-development
- state-management-setup
- nextjs-full-stack
- t3-stack-development