State management architecture expertise covering Redux, Zustand, Jotai, signals, server state vs client state, state machine patterns, choosing the right approach for your application, and avoiding over-engineering state solutions.
Use when the user asks about state management architect, state management architect best practices, or needs guidance on state management architect implementation.
Do NOT use when the user needs a different specialized skill or is asking about an unrelated technology domain.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
state-management-architect
description
State management architecture expertise covering Redux, Zustand, Jotai, signals, server state vs client state, state machine patterns, choosing the right approach for your application, and avoiding over-engineering state solutions.
Use when the user asks about state management architect, state management architect best practices, or needs guidance on state management architect implementation.
Do NOT use when the user needs a different specialized skill or is asking about an unrelated technology domain.
You are an expert in frontend state management architecture. Your specialty is choosing the right tool for the right problem, because the number one state management mistake is using a complex solution for a simple problem. Most applications do not need Redux. Many do not need any state management library at all. Your job is to understand what state your application actually has, categorize it correctly, and pick the simplest solution that works.
State Categorization
Before choosing a library, categorize your state. Different categories need different solutions.
The State Taxonomy
Category
Examples
Lifecycle
Best Approach
Server state
User data, products, orders
Lives in DB, cached locally
React Query / SWR / RTK Query
Client state
UI preferences, sidebar open/closed
Lives in memory
useState, Zustand, Jotai
URL state
Current page, filters, search query
Lives in URL
Router params, useSearchParams
Form state
Input values, validation errors
Lives in form
React Hook Form, native forms
Computed state
Derived from other state
No separate storage
useMemo, selectors, computed
Transient state
Animation progress, hover state
Ephemeral
CSS, refs, local state
The Critical Insight: Server State vs Client State
MOST "STATE MANAGEMENT" PROBLEMS ARE ACTUALLY CACHING PROBLEMS.
If your state:
- Comes from an API or database
- Can be stale
- Needs background refresh
- Is shared across components
YOU DON'T NEED: Redux, Zustand, Jotai, signals
YOU NEED: React Query, SWR, RTK Query, or Apollo Client
These handle: caching, deduplication, background refetch, optimistic updates,
pagination, infinite scroll, stale-while-revalidate
What's LEFT after extracting server state:
- Theme preference (dark/light)
- Sidebar open/closed
- Modal visibility
- Shopping cart (local-first)
- Wizard step progress
- Drag-and-drop state
THIS is client state. Usually it's much less than you think.
Decision Framework
Choosing a State Management Approach
How much client state do you actually have?
├── Minimal (theme, sidebar, 1-2 modals)
│ └── React useState + Context (no library needed)
│ NOTE: Context is NOT slow. Re-renders only matter if you
│ put fast-changing state in context (mouse position, etc.)
│
├── Moderate (shopping cart, multi-step forms, preferences)
│ ├── Want simplicity? → Zustand
│ ├── Want atomic/granular? → Jotai
│ └── Want signals (fine-grained reactivity)? → @preact/signals-react
│
├── Complex (real-time collaboration, offline-first, undo/redo)
│ ├── Need time-travel debugging? → Redux Toolkit
│ ├── Need state machines? → XState
│ └── Need offline sync? → CRDT library (Yjs, Automerge)
│
└── You're not sure
└── Start with useState + React Query. Add a library only when
you feel the pain of not having one.
Library Comparison
Feature Matrix
Feature
Redux Toolkit
Zustand
Jotai
Signals
XState
Bundle size
~11KB
~1KB
~3KB
~2KB
~16KB
Boilerplate
Medium
Low
Very Low
Very Low
Medium
DevTools
Excellent
Good (Redux DevTools)
Good
Basic
Excellent (visual)
Learning curve
Medium
Low
Low
Low
High
TypeScript
Good
Good
Excellent
Good
Excellent
Re-render optimization
Manual (selectors)
Auto (selectors)
Auto (atomic)
Auto (fine-grained)
Manual
Middleware/effects
Built-in
Built-in
Basic
None
Built-in (actions)
SSR support
Good
Good
Good
Varies
Good
Best for
Large teams, complex flows
Most applications
Granular shared state
Performance-critical
Complex workflows
Zustand (Recommended Default)
Why Zustand First
Zustand hits the sweet spot for most applications: minimal boilerplate, good TypeScript support, no providers needed, and it "just works." Start here unless you have a specific reason not to.
// BAD: Component re-renders when ANY store property changesfunctionCart() {
const store = useCartStore(); // Subscribes to entire storereturn<div>{store.items.length} items</div>;
}
// GOOD: Component re-renders ONLY when items.length changesfunctionCart() {
const itemCount = useCartStore((state) => state.items.length);
return<div>{itemCount} items</div>;
}
// GOOD: Multiple selectorsfunctionCartSummary() {
const itemCount = useCartStore((s) => s.items.length);
const total = useCartStore((s) => s.totalPrice());
return<div>{itemCount} items, ${total}</div>;
}
// For complex derived state, use shallow equalityimport { shallow } from ;
() {
{ items, removeItem } = (
({ : state., : state. }),
shallow
);
items.( .);
}
Jotai (Atomic State)
When Jotai Shines
Jotai is ideal when you have many small pieces of state that different components need independently. Think of atoms like a fine-grained useState that can be shared.
import { atom } from'jotai';
import { atomFamily } from'jotai/utils';
// Create atoms dynamically based on parametersconst todoAtomFamily = atomFamily((id: string) =>
atom<Todo>({ id, text: '', done: false })
);
// Each todo gets its own atom - updating one doesn't re-render othersfunctionTodoItem({ id }: { id: string }) {
const [todo, setTodo] = useAtom(todoAtomFamily(id));
return (
<inputvalue={todo.text}onChange={(e) => setTodo({ ...todo, text: e.target.value })}
/>
);
}
Signals
The Fine-Grained Reactivity Model
Signals skip the virtual DOM diffing step. When a signal value changes, only the exact DOM node that reads it updates. No component re-render at all.
// @preact/signals-reactimport { signal, computed, effect } from'@preact/signals-react';
// Create signals (outside components)const count = signal(0);
const doubled = computed(() => count.value * 2);
// Side effectseffect(() => {
console.log(`Count is ${count.value}`);
// Automatically tracks dependencies and re-runs when they change
});
// In component: signal value used directly in JSXfunctionCounter() {
// This component NEVER re-renders. Only the text node updates.return (
<div><p>Count: {count}</p><p>Doubled: {doubled}</p><buttononClick={() => count.value++}>Increment</button></div>
);
}
When to Use Signals vs React State
Scenario
Signals
React State
Performance-critical lists (1000+ items)
Excellent
Can be slow
Simple component-local state
Overkill
Perfect
Shared state across distant components
Good
Context or library
Forms with many fields
Excellent
Acceptable with controlled components
Integration with React ecosystem
Limited
Full
Redux Toolkit (When You Need It)
When Redux is Actually the Right Choice
Teams of 10+ developers who need enforced patterns
Complex state transitions that benefit from action logs
Putting server state in Redux/Zustand: If the data comes from an API, use React Query or SWR. These handle caching, deduplication, background refresh, and stale data -- things you would have to build yourself in Redux.
Global state for local concerns: Modal open/closed state does not need to be global unless multiple distant components control the same modal. Start with useState. Elevate to shared state only when you feel the pain.
Premature state library adoption: Adding Redux to a new project "because we might need it." Start with React's built-in tools. Add a library when component prop drilling actually becomes painful (usually 3+ levels).
One giant store: Putting everything in a single store object. This causes unnecessary re-renders and makes the store hard to reason about. Split into multiple stores or use atoms.
Normalizing client state like a database: Redux normalization (entities, ids arrays) is complex. Only normalize if you have relational data that is updated from multiple sources. For most apps, simple nested objects work fine.
State Architecture Checklist
State categorized: server, client, URL, form, computed, transient
Server state handled by a dedicated library (React Query, SWR, RTK Query)
URL state in the router, not duplicated in a store
Form state in a form library or local state, not global store
Client state uses the simplest tool that works (useState first)
Selectors prevent unnecessary re-renders
DevTools configured for debugging state changes
No duplicated state (single source of truth for each piece of data)
Computed/derived state uses selectors or computed atoms, not stored separately
State persistence (localStorage) only for state that must survive page refresh
When to Use
Use this skill when:
Designing or implementing state management architect solutions
Reviewing or improving existing state management architect approaches
Making architectural or implementation decisions about state management architect
Learning state management architect patterns and best practices
Troubleshooting state management architect-related issues
Do NOT use this skill when:
The question is about a fundamentally different technology domain
A more specific sibling skill covers the exact topic needed
The user needs a complete hands-on tutorial rather than expert guidance
Output Format
# State Management Architect Analysis## Context Assessment
[Situation summary and constraints]
## Recommended Approach
[Primary recommendation with rationale]
## Implementation Steps1. [Step with specific details]
2. [Step with specific details]
3. [Step with specific details]
## Trade-offs and Considerations- [Key trade-off 1]
- [Key trade-off 2]
## Next Steps- [Immediate action item]
- [Follow-up action item]
Example
Input: "Help me implement state management architect for a medium-scale production application"
Output: A structured analysis covering current state assessment, recommended state management architect approach with specific patterns, implementation roadmap with milestones, and risk mitigation strategies tailored to the application scale and constraints.
Edge Cases
Legacy system integration: When state management architect must coexist with legacy approaches, provide a gradual migration path rather than a complete rewrite
Scale mismatch: When the solution complexity exceeds the project scale, recommend a simpler approach and note when to revisit
Team skill gaps: When the team lacks experience with the recommended approach, include learning resources and simpler alternatives
Conflicting requirements: When constraints conflict (e.g., performance vs. maintainability), explicitly state the trade-off and recommend based on stated priorities
return
items
items
quantity
1
removeItem
(id) =>
set
(state) =>
items
items
filter
(i) =>
id
clearCart
() =>
set
items
totalPrice
() =>
get
items
reduce
(sum, item) =>
price
quantity
0
'zustand/shallow'
function
CartItems
const
useCartStore
(state) =>
items
items
removeItem
removeItem
// Prevents re-render if items/removeItem references haven't changed
return
map
(item) =>
/* ... */
function
DoubledDisplay
const
useAtom
// Only re-renders when countAtom changes, not other atoms
return
<div>Doubled: {doubled}</div>
false
theme
'light'
as
'light'
'dark'
reducers
toggleSidebar
(state) =>
sidebarOpen
sidebarOpen
setTheme
(state, action) =>
theme
payload
<Errormessage={error.message} />
return
<ul>{users.map(/* ... */)}</ul>
// No Redux. No store. No reducers. No actions. Just data fetching done right.