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.

Ciza · 0 points · 23 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_plugins_azure-sdk-typescript_skills_zustand-store-ts-e58528d.zip · 2 KB
Part of microsoft/skills — 195 skills

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

  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
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.

No comments yet.

Reviews (0)

No reviews yet.

Related