Claude-skill-registry generate-store-action
Generate Zustand async action with loading/error states and toast notifications. Use when adding new API calls to the health store.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/generate-store-action" ~/.claude/skills/majiayu000-claude-skill-registry-generate-store-action && rm -rf "$T"
manifest:
skills/data/generate-store-action/SKILL.mdsource content
Generate Store Action
Generate a Zustand async action for the health store with loading/error state management.
Usage
When user requests to add a store action, ask for:
- Action name (e.g., "fetchWaterLogs", "addSleepLog", "updateWeight")
- API endpoint (e.g., "/api/water-intake", "/api/sleep")
- HTTP method (GET, POST, PUT, DELETE)
- Request/response types
- State updates needed (what gets stored in Zustand)
Implementation Pattern
Based on
src/lib/store/healthStore.ts existing patterns.
Pattern Structure
Add to existing store in
src/lib/store/healthStore.ts:
// In HealthState interface: interface HealthState { // ... existing state ... waterLogs: WaterLog[]; // ... existing actions ... fetchWaterLogs: (date: string) => Promise<void>; addWaterLog: (log: Omit<WaterLog, 'id' | 'createdAt'>) => Promise<void>; deleteWaterLog: (id: string) => Promise<void>; } // In the store creation: export const useHealthStore = create<HealthState>((set, get) => ({ // ... existing state ... waterLogs: [], // ... existing actions ... fetchWaterLogs: async (date: string) => { set({ isLoading: true, error: null }); try { const response = await fetch(`/api/water-intake?date=${date}`); if (!response.ok) throw new Error('Failed to fetch water logs'); const data = await response.json(); set({ waterLogs: data, isLoading: false }); } catch (err: any) { set({ error: err.message, isLoading: false }); toast.error(err.message || 'Failed to fetch water logs'); } }, addWaterLog: async (log: Omit<WaterLog, 'id' | 'createdAt'>) => { set({ isLoading: true, error: null }); try { const response = await fetch('/api/water-intake', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(log), }); if (!response.ok) throw new Error('Failed to add water log'); const newLog = await response.json(); set({ waterLogs: [...get().waterLogs, newLog], isLoading: false, }); toast.success('Water intake logged'); } catch (err: any) { set({ error: err.message, isLoading: false }); toast.error(err.message || 'Failed to add water log'); } }, deleteWaterLog: async (id: string) => { set({ isLoading: true, error: null }); try { const response = await fetch(`/api/water-intake?id=${id}`, { method: 'DELETE', }); if (!response.ok) throw new Error('Failed to delete water log'); set({ waterLogs: get().waterLogs.filter((log) => log.id !== id), isLoading: false, }); toast.success('Water log deleted'); } catch (err: any) { set({ error: err.message, isLoading: false }); toast.error(err.message || 'Failed to delete water log'); } }, }));
Key Conventions
- Always wrap in
set({ isLoading: true, error: null }) - Use
with proper method and headersawait fetch() - Check
to handle HTTP errors!response.ok - Parse response with
await response.json() - Use
to access current state in actionsget() - Update state with
includingset()isLoading: false - Call
on successtoast.success() - Call
on failuretoast.error() - Include error message in toast:
err.message || 'Default message' - For arrays: use spread operator to create new array
- State updates are immutable (don't mutate existing state)
Steps
- Ask user for action name, API endpoint, method, and types
- Open
src/lib/store/healthStore.ts - Add action type to HealthState interface
- Add initial state if needed (empty array, null, etc.)
- Implement action function following the pattern above
- Include proper error handling and toast notifications
- Format with Prettier
Implementation Checklist
- Action added to HealthState interface
- Initial state added if new data field
- Async action with try-catch
- Loading state managed (set/unset)
- Error state managed
- API endpoint correct
- HTTP method correct
- Response validation (!response.ok)
- Toast notifications added
- State updates are immutable
- get() used to access current state