Home › React › Zustand state management Cursor rules

Zustand state management Cursor rules

Cursor rules for React state with Zustand: small typed stores, selectors, actions in the store, persist and devtools middleware, and testing.

CursorReact

How to use

Save this as .cursor/rules/zustand.mdc in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.

Note: Review and test before use. Provided as is, without warranty. See Terms.

.cursor/rules/zustand.mdcDownload  
---
description: Zustand store conventions
globs: ["src/**/*.{ts,tsx}"]
alwaysApply: false
---

# Zustand

- Use Zustand for client UI state only (filters, panels, drafts, session-local preferences). Server data belongs in TanStack Query/SWR/loaders, not in a store.
- One store per domain in `src/stores/<domain>.ts`, created with `create<State>()((set, get) => ({ ... }))` (note the curried call for TypeScript).
- State and actions live together; components call `useCartStore((s) => s.addItem)`. No `setState` calls scattered across components.
- Always select the smallest slice: `useCartStore((s) => s.items.length)`. When selecting several values, use `useShallow` from `zustand/react/shallow` to avoid re-render loops.
- Never return a new object/array from a selector without `useShallow`; it re-renders every time.
- Update immutably with `set((s) => ({ items: [...s.items, item] }))`, or add the `immer` middleware if the repo already uses it.
- Middleware order: `devtools(persist(immer(...)))` as needed. `persist` needs a unique `name`, a `version` and a `migrate` when the shape changes; use `partialize` to persist only what must survive reloads.
- Derived values: compute in selectors or small helper hooks, not stored copies.
- For Next.js/SSR, create the store per request with `createStore` + a React context provider; a module-level store leaks state between users.

## Tests
Reset the store in `beforeEach` (`useStore.setState(initialState, true)`) and test actions directly.

## Done when
`npx tsc --noEmit`, lint and tests pass.

More: all React rules · all Cursor rules

Related rules

React + TypeScript Copilot path instructions

Path-specific Copilot instructions for React 19 + TypeScript .tsx files: components, hooks, accessibility, and tests.

GitHub CopilotReact

React 19 + Vite SPA rules

Cursor rules for React 19 single-page apps on Vite 6+ with TypeScript, hooks, and Vitest.

CursorReact

Redux Toolkit + RTK Query Copilot path instructions

Path-specific Copilot instructions for Redux Toolkit: createSlice, typed hooks, RTK Query endpoints with tags, and no legacy Redux patterns.

GitHub CopilotReact

TanStack Query v5 rules

Cursor rules for TanStack Query v5 in React: query keys, queryOptions, mutations, and cache invalidation.

CursorReact

Astro content site rules

Cursor rules for Astro 5 sites with content collections, islands, and zero-JS-by-default pages.

CursorAstro

Chrome extension (Manifest V3) rules

Cursor rules for building Manifest V3 browser extensions with TypeScript and minimal permissions.

CursorChrome extensions

Get the best new AI prompts every week

One short email a week: the best new prompts and rules for ChatGPT, Claude, Gemini, Midjourney, Cursor and more, plus what changed in the tools. Free, unsubscribe anytime.

Finishes on our newsletter page at beehiiv (opens in a new tab). Or subscribe directly.