Cursor rule
.cursor/rules/zustand-store.mdc# Guidelines for Zustand Store
Cursor rules
Quality
74/100
Scores the file, not the repository.Length
627 words
19 headings · 4 code blocksRepository
15
— · pushed 231 days agoLast changed
3 days ago
First indexed 3 days ago.123456# Guidelines for Zustand Stores78## Purpose and Overview9Zustand stores provide centralized state management with a simple API that doesn't require providers or complex setup. They are used to manage application state that needs to be accessed by multiple components, especially across different parts of the component tree. The stores in this project follow a consistent pattern using immer middleware for immutable state updates.1011## Structure and Organization1213### Store Module Structure14```15src/16├── stores/ # Shared stores module17│ └── use-[entity]-store.ts # Store for specific entity18└── features/19 └── [feature-name]/20 └── _stores/ # Feature-specific stores21 └── use-[entity]-store.ts # Feature-specific store22```2324## Naming Conventions2526### Files27- `use-[entity]-store.ts`: For store files, use kebab-case2829### Types30- `[Entity]StoreState`: Type for store state31- `[Entity]StoreActions`: Type for store actions32- `[Entity]Store`: Combined type for state and actions33- `DEFAULT_[ENTITY]_STORE_STATE`: Constant for default store state3435### Functions36- `use[Entity]Store`: The zustand hook for accessing the store3738## Implementation Guidelines3940### Store Creation41- Use zustand with immer middleware for immutable updates42- Separate state and actions with explicit types43- Define a default state constant44- Export the combined store type and hook4546### State Management47- Keep state minimal and focused on a specific domain48- Use immer's state mutation syntax in actions49- Avoid storing derived state that can be computed5051### Example Store Implementation52```typescript53import { create } from 'zustand';54import { immer } from 'zustand/middleware/immer';5556// Define the state type57export type CounterStoreState = {58 count: number;59};6061// Define the actions type62export type CounterStoreActions = {63 increment: () => void;64 decrement: () => void;65 reset: () => void;66 setCount: (count: number) => void;67};6869// Default state constant70export const DEFAULT_COUNTER_STORE_STATE: CounterStoreState = {71 count: 0,72};7374// Combined store type75export type CounterStore = CounterStoreState & CounterStoreActions;7677// Create and export the store hook78export const useCounterStore = create(79 immer<CounterStore>(set => ({80 ...DEFAULT_COUNTER_STORE_STATE,8182 /* Actions */83 increment: () => {84 set(state => {85 state.count += 1;86 });87 },88 decrement: () => {89 set(state => {90 state.count -= 1;91 });92 },93 reset: () => {94 set(state => {95 state.count = DEFAULT_COUNTER_STORE_STATE.count;96 });97 },98 setCount: (count) => {99 set(state => {100 state.count = count;101 });102 },103 }))104);105```106107### Example Store Test108```typescript109import { describe, it, expect, beforeEach } from 'vitest';110import { useCounterStore, DEFAULT_COUNTER_STORE_STATE } from './use-counter-store';111112describe('useCounterStore', () => {113 beforeEach(() => {114 useCounterStore.setState(DEFAULT_COUNTER_STORE_STATE);115 });116117 it('should initialize with default state', () => {118 expect(useCounterStore.getState().count).toBe(0);119 });120121 it('should increment the count', () => {122 useCounterStore.getState().increment();123 expect(useCounterStore.getState().count).toBe(1);124 });125126 it('should decrement the count', () => {127 useCounterStore.getState().increment();128 useCounterStore.getState().decrement();129 expect(useCounterStore.getState().count).toBe(0);130 });131132 it('should reset the count', () => {133 useCounterStore.getState().increment();134 useCounterStore.getState().reset();135 expect(useCounterStore.getState().count).toBe(0);136 });137138 it('should set the count to a specific value', () => {139 useCounterStore.getState().setCount(10);140 expect(useCounterStore.getState().count).toBe(10);141 });142});143```144145## Best Practices146147### Performance Considerations148- Use selectors when accessing store values to prevent unnecessary re-renders149- Keep the state structure flat when possible150- Use multiple small, focused stores instead of one large store151152### Accessing Stores in Components153- Use selectors to extract only the state needed by a component154```typescript155// Good: Using a selector156const count = useCounterStore(state => state.count);157158// Avoid: Grabbing the entire state159const { count } = useCounterStore();160```161162### Store Composition163- For complex state management, consider composing multiple stores164- Use separate stores for unrelated parts of the application state165- Consider creating a store factory for related but separate instances166167### Persistence168- For persistent state, consider using zustand/middleware/persist169- Define clear strategies for state rehydration170- Handle loading states during rehydration171172### TypeScript Integration173- Always define explicit types for state and actions174- Use discriminated unions for complex state transitions175- Leverage TypeScript to ensure type safety throughout the application
Also in constROD/template-react-vite
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| constROD/template-react-vite.cursor/rules/data-access-via-api.mdc · 15 | Cursor rules | teststylearchtypes+1 | 74/100 | 3 days ago | |
| constROD/template-react-vite.cursor/rules/design-system.mdc · 15 | Cursor rules | lint-formatstylearchui | 58/100 | 3 days ago | |
| constROD/template-react-vite.cursor/rules/mutation-hooks.mdc · 15 | Cursor rules | stylearchtypes | 70/100 | 3 days ago | |
| constROD/template-react-vite.cursor/rules/project-structure.mdc · 15 | Cursor rules | stylearchdependencies | 78/100 | 3 days ago | |
| constROD/template-react-vite.cursor/rules/query-hooks.mdc · 15 | Cursor rules | stylearchtypesperformance | 70/100 | 3 days ago | |
| constROD/template-react-vite.cursor/rules/service-layer.mdc · 15 | Cursor rules | stylearchtypes | 66/100 | 3 days ago | |
| constROD/template-react-vite.cursor/rules/styling.mdc · 15 | Cursor rules | archui | 58/100 | 3 days ago | |
| constROD/template-react-viteAGENTS.md · 15 | AGENTS.md | testlint-formatstylearch+3 | 90/100 | 3 days ago | |
| constROD/template-react-viteCLAUDE.md · 15 | CLAUDE.md | testlint-formatstylearch+3 | 90/100 | 3 days ago |
Diff against .cursor/rules/data-access-via-api.mdc Diff against .cursor/rules/design-system.mdc Diff against .cursor/rules/mutation-hooks.mdc Diff against .cursor/rules/project-structure.mdc Diff against .cursor/rules/query-hooks.mdc Diff against .cursor/rules/service-layer.mdc Diff against .cursor/rules/styling.mdc Diff against AGENTS.md Diff against CLAUDE.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 3 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 3 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 3 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 3 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 3 days ago |
