home / skills / sickn33 / antigravity-awesome-skills / zustand-store-ts

zustand-store-ts skill

/skills/zustand-store-ts

This skill helps you create and manage Zustand stores with TypeScript, subscribeWithSelector, and clean state-action separation for React apps.

npx playbooks add skill sickn33/antigravity-awesome-skills --skill zustand-store-ts

Review the files below or copy the command above to add this skill to your agents.

Files (1)
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.
---

# 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`

Overview

This skill generates ready-to-use Zustand stores in TypeScript that follow proven patterns: typed state/action separation, subscribeWithSelector middleware, and per-selector reactivity. It provides a template and guidance to create global or feature stores for React apps, with testing and export conventions included.

How this skill works

The skill scaffolds a TypeScript store template that composes state and actions into a single typed store type, wraps the store with subscribeWithSelector, and enforces individual selectors for minimal re-renders. It also includes examples for subscribing outside React and recommendations for where to place and export stores in a codebase.

When to use it

  • Building global or feature-level state for React apps using Zustand and TypeScript.
  • When you need reactive selections to avoid unnecessary component re-renders.
  • Implementing testable, well-typed stores with clear separation of state and actions.
  • Adding subscriptions outside React (e.g., logging, syncing, or cross-module reactions).
  • Migrating plain context or reducer patterns to a lightweight, global store solution.

Best practices

  • Always wrap create() with subscribeWithSelector to enable efficient selectors and subscriptions.
  • Define State and Actions as separate TypeScript interfaces and export a combined Store type.
  • Use individual selectors in components to limit re-renders to only the values a component uses.
  • Keep store files in a dedicated folder (e.g., src/frontend/src/store/) and export from a central index.
  • Add unit tests for actions and side effects to ensure predictable behavior and easier refactors.

Example use cases

  • A Project store that manages lists, loading state, and CRUD actions for a dashboard.
  • A global auth store exposing currentUser, isAuthenticated, and login/logout actions.
  • A UI preferences store for theme, locale, and persisted settings across sessions.
  • Subscribing to a selectedId outside React to trigger analytics or side effects.
  • Creating feature-scoped stores for real-time widgets where minimal re-rendering is critical.

FAQ

Why use subscribeWithSelector?

subscribeWithSelector enables fine-grained selectors and external subscriptions so components and non-UI code only react to relevant state changes, reducing unnecessary re-renders.

How should I structure types for a store?

Declare separate interfaces for State and Actions, then export a combined Store type (State & Actions) so types are explicit and reusable in components and tests.