• Home
  • About
  • Agent Skills
  • Projects
  • Blog
  • Contact
Resume
Agent Skills/architecture/Review State Boundaries in React Architecture

Review State Boundaries in React Architecture

Classify React state as local, server, URL, or global client state, establish a source of truth, and remove duplicated ownership without introducing unnecessary stores.

reactstate-managementserver-stateurl-statearchitecturerefactoring

Install for your agent

Download the file and place it at the path for your coding agent. Review the instructions before enabling a third-party skill.

Codex

~/.codex/skills/state-boundary-architecture-review/SKILL.md

Claude Code

.claude/skills/state-boundary-architecture-review/SKILL.md

Cursor

.cursor/skills/state-boundary-architecture-review/SKILL.md

GitHub Copilot

.github/skills/state-boundary-architecture-review/SKILL.md
</>View raw SKILL.mdInspect only the executable instructions your coding agent will receive, without catalog metadata.
Source file: state-boundary-architecture-review/SKILL.md
---
name: "state-boundary-architecture-review"
description: "Classify React state as local, server, URL, or global client state, establish a source of truth, and remove duplicated ownership without introducing unnecessary stores."
---

# Review State Boundaries in React Architecture

Use this skill when the same data is mirrored across stores, hooks, query caches, URLs, or components; synchronization Effects are multiplying; or the source of truth is unclear.

The goal is not to choose a favorite state library. Classify ownership first, then keep the smallest mechanism that matches the data lifecycle.

## State ownership model

```text
Local UI state      → nearest owning component
Server state        → cache/data layer
URL state           → router/search params
Global client state → truly application-wide browser state
Derived state       → compute it instead of storing it
```

These are decision categories, not rigid folder rules. Lifecycle and authority decide ownership.

## Workflow

### 1. Build a state inventory

```text
State:
Source of truth:
Readers:
Writers:
Lifetime:
Must survive navigation?
Must be shareable in URL?
Comes from server?
```

### 2. Detect duplicate authority

Prioritize cases where query results are copied into Redux or Zustand, search params are mirrored in `useState`, derived values are synchronized by Effects, parent and child both own editable copies, or persistence is enabled without a product requirement.

### 3. Separate server and client state

Data whose authoritative source is an API normally belongs in the server-state layer:

```text
API
 ↓
Query cache
 ↓
UI
```

Do not move modal visibility, a local selected tab, or an unsaved form draft into a query cache simply because multiple components can see it.

### 4. Use the URL for navigational state

Filters, sorting, pagination, and tabs are strong URL candidates when refresh, browser navigation, or link sharing should preserve them. Avoid maintaining a second local mirror unless the product explicitly needs an unapplied draft.

### 5. Compute derived values

```tsx
// avoid
const [fullName, setFullName] = useState("")
useEffect(() => {
  setFullName(`${firstName} ${lastName}`)
}, [firstName, lastName])

// prefer
const fullName = `${firstName} ${lastName}`
```

### 6. Make global client state the last option

Before moving data there, ask whether it can stay local, already belongs to server state, belongs in the URL, or only needs a subtree-scoped context.

### 7. Remove synchronization before adding abstractions

Audit Effects whose only purpose is keeping two representations aligned. Deleting duplicate state often solves the architecture problem more directly than adding selectors, middleware, or another state library.

## Expected output

```text
State:
Current owner:
Problem:
Recommended owner:
Migration:
Risk:
Validation:
```

Do not migrate state merely to standardize tooling. The desired outcome is fewer sources of truth, less manual synchronization, and clearer ownership.

After refactoring, validate refresh behavior, navigation and back/forward, loading and error paths, relevant optimistic mutations, and the repository's existing checks.

Use this skill when the same data is mirrored across stores, hooks, query caches, URLs, or components; synchronization Effects are multiplying; or the source of truth is unclear.

The goal is not to choose a favorite state library. Classify ownership first, then keep the smallest mechanism that matches the data lifecycle.

State ownership model

Local UI state      → nearest owning component
Server state        → cache/data layer
URL state           → router/search params
Global client state → truly application-wide browser state
Derived state       → compute it instead of storing it

These are decision categories, not rigid folder rules. Lifecycle and authority decide ownership.

Workflow

1. Build a state inventory

State:
Source of truth:
Readers:
Writers:
Lifetime:
Must survive navigation?
Must be shareable in URL?
Comes from server?

2. Detect duplicate authority

Prioritize cases where query results are copied into Redux or Zustand, search params are mirrored in useState, derived values are synchronized by Effects, parent and child both own editable copies, or persistence is enabled without a product requirement.

3. Separate server and client state

Data whose authoritative source is an API normally belongs in the server-state layer:

API
 ↓
Query cache
 ↓
UI

Do not move modal visibility, a local selected tab, or an unsaved form draft into a query cache simply because multiple components can see it.

4. Use the URL for navigational state

Filters, sorting, pagination, and tabs are strong URL candidates when refresh, browser navigation, or link sharing should preserve them. Avoid maintaining a second local mirror unless the product explicitly needs an unapplied draft.

5. Compute derived values

// avoid
const [fullName, setFullName] = useState("")
useEffect(() => {
  setFullName(`${firstName} ${lastName}`)
}, [firstName, lastName])

// prefer
const fullName = `${firstName} ${lastName}`

6. Make global client state the last option

Before moving data there, ask whether it can stay local, already belongs to server state, belongs in the URL, or only needs a subtree-scoped context.

7. Remove synchronization before adding abstractions

Audit Effects whose only purpose is keeping two representations aligned. Deleting duplicate state often solves the architecture problem more directly than adding selectors, middleware, or another state library.

Expected output

State:
Current owner:
Problem:
Recommended owner:
Migration:
Risk:
Validation:

Do not migrate state merely to standardize tooling. The desired outcome is fewer sources of truth, less manual synchronization, and clearer ownership.

After refactoring, validate refresh behavior, navigation and back/forward, loading and error paths, relevant optimistic mutations, and the repository's existing checks.

Skill details

Version
1.0.0
Updated
2026-09-11
Category
architecture
Difficulty
advanced
License
MIT
Author
Naser Rasouli

Capabilities

Executes scriptsNot required
Network accessNot required

Source article

Read the original article behind this skill for deeper explanations, context, and examples.