Last updated: March 16, 2026
CursorRules offer a powerful way to communicate your team’s state management patterns to Cursor. When configured correctly, these rules guide the AI to generate code that aligns with your existing architecture, whether you use React Context, Redux Toolkit, Vue’s Composition API, or Zustand. This guide shows you how to write effective CursorRules that capture your team’s specific patterns.
Table of Contents
- Why State Management Patterns Matter in CursorRules
- Prerequisites
- Common Mistakes to Avoid
- Advanced State Patterns: Persistence and Sync
- When to Lift State
- Troubleshooting
Why State Management Patterns Matter in CursorRules
Every team develops unique approaches to handling application state. Some prefer centralized stores with Redux Toolkit, others favor distributed patterns with React hooks, and some use Zustand for its simplicity. When Cursor generates new components or modifies existing code, it needs to understand these patterns to produce consistent results.
CursorRules act as a persistent instruction set that Cursor references when working on your codebase. Unlike general-purpose prompts, team-specific rules encode conventions that make your codebase cohesive. The key is specificity—vague instructions produce generic code, while detailed patterns produce code that feels like it was written by a team member.
Prerequisites
Before you begin, make sure you have the following ready:
- A computer running macOS, Linux, or Windows
- Terminal or command-line access
- Administrator or sudo privileges (for system-level changes)
- A stable internet connection for downloading tools
Step 1: Writing Effective State Management CursorRules
Effective CursorRules follow a structured approach: define the pattern, show concrete examples, and specify any constraints. Here’s a framework you can adapt:
# State Management Patterns
### Step 2: Our Redux Toolkit Setup
- We use Redux Toolkit with createSlice for all global state
- Slices live in /src/store/slices/
- Each slice includes: name, initialState, reducers, and async thunks
- Selectors are created with createSelector and stored in /src/store/selectors/
### Step 3: Component State Patterns
- Local state uses useState with explicit type annotations
- useState is preferred over useReducer unless complex state transitions exist
- Form state uses controlled components with onChange handlers
### Step 4: State Access in Components
- Always import selectors from /src/store/selectors/
- Use useSelector and useDispatch hooks from react-redux
- Never access store state directly—always use selectors
This structure gives Cursor clear guidance on where state lives, how it’s organized, and how components should interact with it.
Step 5: Pattern Examples for Different Frameworks
React Context Pattern
If your team uses React Context for state management, include specific guidance about Context providers and custom hooks:
### Step 6: React Context Patterns
- Global UI state lives in /src/context/
- Each context has a Provider component and useContext hook
- Custom hooks wrap useContext with proper TypeScript types
- Context values are memoized with useMemo to prevent unnecessary re-renders
Example context structure:
/src/context/
ThemeContext.tsx # Theme provider and useTheme hook
AuthContext.tsx # Auth provider and useAuth hook
NotificationContext.tsx # Toast notifications
Zustand Pattern
Zustand offers a simpler alternative to Redux. Your CursorRules should reflect its minimal approach:
### Step 7: Zustand Store Pattern
- All stores use create from zustand
- Stores include TypeScript interfaces for state and actions
- Slices pattern not required—single store per domain
- Actions are defined as functions within the store
Example store:
/src/stores/
useUserStore.ts # User authentication state
useCartStore.ts # Shopping cart state
useUIStore.ts # UI visibility and modals
Redux Toolkit with createAsyncThunk
For teams using Redux Toolkit with async operations, specify how to handle API calls:
### Step 8: Async State with Redux Toolkit
- Use createAsyncThunk for all API calls
- Handle loading, success, and failure states in extraReducers
- Use useQuery from RTK Query for server-state when possible
- Normalize API responses using createEntityAdapter for large lists
Step 9: Integrate Rules with Project Structure
CursorRules work best when they reference your actual directory structure. Include a section that maps patterns to file locations:
### Step 10: File Organization
State-related files follow these locations:
| Pattern Type | Directory |
|-------------|-----------|
| Redux slices | /src/store/slices/ |
| Redux selectors | /src/store/selectors/ |
| React Context | /src/context/ |
| Zustand stores | /src/stores/ |
| API services | /src/services/ |
| Custom hooks | /src/hooks/ |
When creating new state, check if a pattern already exists in these directories.
This mapping helps Cursor place new files in the correct locations and understand relationships between different state management approaches.
Step 11: Test State Management Code
Include guidance on how your team tests state logic:
### Step 12: Test State Management
- Redux slices: test reducers in isolation with jest
- Custom hooks: test with @testing-library/react-hooks
- Integration: test connected components with mocked store
- Async thunks: use redux-saga-test-plan or waitFor from @testing-library
Common Mistakes to Avoid
When writing CursorRules for state management, avoid these pitfalls:
-
Being too generic: “Use state management” tells Cursor nothing. Instead, specify “Use Redux Toolkit with createSlice for global state.”
-
Missing examples: Abstract descriptions confuse AI models. Show actual code patterns from your codebase.
-
Ignoring TypeScript: If your project uses TypeScript (and it should), include type definitions in your rules.
-
No constraints: Specify what NOT to do. “Don’t use useState for global data” prevents common mistakes.
Step 13: Updating Rules as Patterns Evolve
Your state management approach will evolve. Set up a process to keep CursorRules current:
-
Review rules during code reviews when state patterns change
-
Add new patterns when introducing libraries or approaches
-
Remove deprecated patterns that your team no longer uses
-
Test new developers’ code generation against rules
Advanced State Patterns: Persistence and Sync
Beyond basic state management, include patterns for persistence and client-server sync. These are frequent sources of inconsistency:
### Step 14: Persistence Patterns
### LocalStorage and SessionStorage
- Critical data (auth tokens, user preferences) uses localStorage with encryption
- Session state uses sessionStorage only—cleared on tab close
- Implement debounced writes to avoid excessive re-renders
- Validate localStorage data on app load; reset if schema mismatches
### IndexedDB for Complex Data
- Large datasets (>1MB) use IndexedDB with proper indexes
- Maintain a version number for schema migrations
- Use promises or async/await consistently
This prevents developers from accidentally storing sensitive data in plain localStorage or querying unindexed databases.
Step 15: State Boundaries and Lifting Rules
Help Cursor understand when to lift state up the component tree:
## When to Lift State
State should be lifted to a common ancestor when:
- Multiple components need the same data
- A sibling component depends on another sibling's state changes
- Parent components need to coordinate multiple children
Example: If both Header and SidebarMenu need current user data,
lift the user state to a shared context or Redux store rather than
fetching separately in each component.
This guidance prevents the common mistake of duplicating data in separate useState hooks.
Step 16: Error Handling Within State
Add specific guidance on managing error states:
### Step 17: Error State Patterns
- Error states live alongside data states (loading, error, success)
- Use discriminated unions: {status: 'error', error: {...}} vs {status: 'success', data: {...}}
- Never throw errors in reducers—catch and log in thunks
- Clear errors when retrying—don't persist old errors
- Distinguish network errors from validation errors in state structure
This prevents state becoming inconsistent when errors occur.
Step 18: Real Example: Complete State Management Rule Set
Here’s a CursorRule combining multiple patterns:
# State Management Architecture
### Step 19: Redux Toolkit with RTK Query
### Directory Structure
- /src/store/slices/ - Redux Toolkit slices
- /src/store/selectors/ - Memoized selectors using createSelector
- /src/hooks/useAppDispatch.ts - Typed dispatch hook
- /src/hooks/useAppSelector.ts - Typed selector hook
- /src/api/ - RTK Query definitions
### RTK Query Rules
- All server state uses RTK Query, not manual Redux
- Invalidate tags on mutations to auto-refetch related queries
- Use skip: true for conditional queries instead of calling hooks conditionally
- Define tags carefully: "Posts List" for collections, "Post" with ID for individual items
### Reducer and Action Rules
- Reducers handle state shape changes only
- Reducers do NOT contain side effects or external calls
- Complex logic lives in createAsyncThunk, not reducers
- Use Immer syntax: state.items[0].completed = true (mutate-like syntax)
### Selector Rules
- Always use createSelector for computed state
- Selectors prevent unnecessary re-renders via memoization
- Create separate selectors for each piece of state
- Selectors receive entire state, return specific subset
### Example Pattern
function MyComponent() {
const dispatch = useAppDispatch();
const items = useAppSelector(selectAllItems);
const loading = useAppSelector(selectItemsLoading);
useEffect(() => {
if (items.length === 0 && !loading) {
dispatch(fetchItems());
}
}, [dispatch, items, loading]);
}
With this rule set, Cursor generates code that feels consistent with established patterns.
Step 20: Test State-Generated Code
Include testing expectations in CursorRules:
### Step 21: Test State Code
- Redux slices: Unit test reducers with specific state transitions
- Selectors: Verify they return expected values and filter correctly
- Async thunks: Mock APIs and test pending/fulfilled/rejected states
- Connected components: Use Redux MockStore to verify dispatched actions
- RTK Query: Use setupServer (MSW) to mock API responses
This ensures Cursor generates testable state code when you ask for it.
Troubleshooting
Configuration changes not taking effect
Restart the relevant service or application after making changes. Some settings require a full system reboot. Verify the configuration file path is correct and the syntax is valid.
Permission denied errors
Run the command with sudo for system-level operations, or check that your user account has the necessary permissions. On macOS, you may need to grant terminal access in System Settings > Privacy & Security.
Connection or network-related failures
Check your internet connection and firewall settings. If using a VPN, try disconnecting temporarily to isolate the issue. Verify that the target server or service is accessible from your network.
Frequently Asked Questions
Who is this article written for?
This article is written for developers, technical professionals, and power users who want practical guidance. Whether you are evaluating options or implementing a solution, the information here focuses on real-world applicability rather than theoretical overviews.
How current is the information in this article?
We update articles regularly to reflect the latest changes. However, tools and platforms evolve quickly. Always verify specific feature availability and pricing directly on the official website before making purchasing decisions.
Does Cursor offer a free tier?
Most major tools offer some form of free tier or trial period. Check Cursor’s current pricing page for the latest free tier details, as these change frequently. Free tiers typically have usage limits that work for evaluation but may not be sufficient for daily professional use.
Can I trust these tools with sensitive data?
Review each tool’s privacy policy, data handling practices, and security certifications before using it with sensitive data. Look for SOC 2 compliance, encryption in transit and at rest, and clear data retention policies. Enterprise tiers often include stronger privacy guarantees.
What is the learning curve like?
Most tools discussed here can be used productively within a few hours. Mastering advanced features takes 1-2 weeks of regular use. Focus on the 20% of features that cover 80% of your needs first, then explore advanced capabilities as specific needs arise.
Related Articles
- Create CursorRules That Enforce Your Team’s Git
- Writing CursorRules for Golang Projects with Specific
- Writing Effective CursorRules for React TypeScript Projects
- How to Create .cursorrules That Enforce Your Teams React
- How to Use AI for Writing Effective Terraform State Manageme
- How to Create Remote Employee Exit Interview Process Built by theluckystrike — More at zovo.one