GitHub Copilot
ChatGPT
Claude
Codex CLI
Cursor
opencode
Skill
Text
zustand-store-ts
Create Zustand stores with TypeScript, subscribeWithSelector middleware, and proper state/action separation. Use when building React state management, creating global stores, or implementing reactive state patterns with Zustand.
Virus-scanned
Reviewed automatically before listing.
Download
microsoft-skills-.github_plugins_azure-sdk-typescript_skills_zustand-store-ts-e58528d.zip · 2 KB
Install
skills CLI
npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-typescript/skills/zustand-store-ts
Claude Code
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git
git clone https://github.com/microsoft/skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Zustand Store
Create Zustand stores following established patterns with proper TypeScript types and middleware.
Quick Start
Copy the template from assets/template.ts and replace placeholders:
{{StoreName}}→ PascalCase store name (e.g.,Project){{description}}→ Brief description for JSDoc
Always Use subscribeWithSelector
import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
export const useMyStore = create<MyStore>()(
subscribeWithSelector((set, get) => ({
// state and actions
}))
);
Separate State and Actions
export interface MyState {
items: Item[];
isLoading: boolean;
}
export interface MyActions {
addItem: (item: Item) => void;
loadItems: () => Promise<void>;
}
export type MyStore = MyState & MyActions;
Use Individual Selectors
// Good - only re-renders when `items` changes
const items = useMyStore((state) => state.items);
// Avoid - re-renders on any state change
const { items, isLoading } = useMyStore();
Subscribe Outside React
useMyStore.subscribe(
(state) => state.selectedId,
(selectedId) => console.log('Selected:', selectedId)
);
Integration Steps
- Create store in
src/frontend/src/store/ - Export from
src/frontend/src/store/index.ts - Add tests in
src/frontend/src/store/*.test.ts
Files (skills)
-
assets
-
template.ts 3.3 KB
import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; // ============================================================================ // Types // ============================================================================ /** * {{StoreName}}State - The state shape for this store */ export interface {{StoreName}}State { // Add state properties items: unknown[]; selectedId: string | null; isLoading: boolean; error: string | null; } /** * {{StoreName}}Actions - Actions that can be performed on this store */ export interface {{StoreName}}Actions { // Setters setItems: (items: unknown[]) => void; setSelectedId: (id: string | null) => void; setLoading: (loading: boolean) => void; setError: (error: string | null) => void; // Complex actions loadItems: () => Promise<void>; addItem: (item: unknown) => void; removeItem: (id: string) => void; // Reset reset: () => void; } /** * {{StoreName}}Store - Combined store type */ export type {{StoreName}}Store = {{StoreName}}State & {{StoreName}}Actions; // ============================================================================ // Initial State // ============================================================================ const initialState: {{StoreName}}State = { items: [], selectedId: null, isLoading: false, error: null, }; // ============================================================================ // Store // ============================================================================ /** * use{{StoreName}}Store - Zustand store for managing {{description}} * * @example * ```typescript * // In a component - use individual selectors for performance * const items = use{{StoreName}}Store((state) => state.items); * const loadItems = use{{StoreName}}Store((state) => state.loadItems); * * // Subscribe to changes outside React * use{{StoreName}}Store.subscribe( * (state) => state.selectedId, * (selectedId) => console.log('Selected:', selectedId) * ); * ``` */ export const use{{StoreName}}Store = create<{{StoreName}}Store>()( subscribeWithSelector((set, get) => ({ // Initial state ...initialState, // Simple setters setItems: (items) => set({ items }), setSelectedId: (selectedId) => set({ selectedId }), setLoading: (isLoading) => set({ isLoading }), setError: (error) => set({ error }), // Async action example loadItems: async () => { set({ isLoading: true, error: null }); try { // const items = await fetchItems(); const items: unknown[] = []; // Replace with actual fetch set({ items, isLoading: false }); } catch (error) { set({ error: error instanceof Error ? error.message : 'Failed to load', isLoading: false, }); } }, // Add item (immutable update) addItem: (item) => { set({ items: [...get().items, item] }); }, // Remove item (immutable update) removeItem: (id) => { set({ items: get().items.filter((item) => (item as { id: string }).id !== id), // Clear selection if removed item was selected selectedId: get().selectedId === id ? null : get().selectedId, }); }, // Reset to initial state reset: () => set(initialState), })) );
-
-
SKILL.md 1.7 KB
--- name: zustand-store-ts description: Create Zustand stores with TypeScript, subscribeWithSelector middleware, and proper state/action separation. Use when building React state management, creating global stores, or implementing reactive state patterns with Zustand. license: MIT metadata: author: Microsoft version: "1.0.0" --- # Zustand Store Create Zustand stores following established patterns with proper TypeScript types and middleware. ## Quick Start Copy the template from [assets/template.ts](assets/template.ts) and replace placeholders: - `{{StoreName}}` → PascalCase store name (e.g., `Project`) - `{{description}}` → Brief description for JSDoc ## Always Use subscribeWithSelector ```typescript import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; export const useMyStore = create<MyStore>()( subscribeWithSelector((set, get) => ({ // state and actions })) ); ``` ## Separate State and Actions ```typescript export interface MyState { items: Item[]; isLoading: boolean; } export interface MyActions { addItem: (item: Item) => void; loadItems: () => Promise<void>; } export type MyStore = MyState & MyActions; ``` ## Use Individual Selectors ```typescript // Good - only re-renders when `items` changes const items = useMyStore((state) => state.items); // Avoid - re-renders on any state change const { items, isLoading } = useMyStore(); ``` ## Subscribe Outside React ```typescript useMyStore.subscribe( (state) => state.selectedId, (selectedId) => console.log('Selected:', selectedId) ); ``` ## Integration Steps 1. Create store in `src/frontend/src/store/` 2. Export from `src/frontend/src/store/index.ts` 3. Add tests in `src/frontend/src/store/*.test.ts`
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.