WEB ATELIER (UDIT) Β· Learning by doing, with theory, practice and shared reflection

State Architecture: Scaling Beyond Components

Draft

URL: https://ruvebal.github.io/web-atelier-udit/lessons/en/react/react-state-architecture/

πŸ“‹ Table of Contents

β€œWhen state grows beyond a component, architecture becomes your ally or your enemy.”


🎯 Sprint Goal

By the end of this sprint: Implement a scalable state architecture that enables features across your app to communicateβ€”whether that’s a shopping cart, auth status, or theme settings.


πŸ“ Position in Journey

Sprint Focus Your App Grows
5. Fundamentals Components, JSX, Props Component library skeleton
6. Hooks State & effects Interactive components
β†’ 7. Architecture Global state Connected features
8. Routing Navigation Multi-page structure

🧭 Learning Objectives

By the end of this lesson, you will:

  • Decide when local state isn’t enough
  • Implement useReducer for complex state logic
  • Share state via React Context
  • Integrate Zustand for lightweight global state
  • Understand Redux patterns (conceptually)
  • Structure your app’s state by domain

πŸ—οΈ What We’ll Build This Sprint

State Domains for Your App

// Organize state by domain:

src/
β”œβ”€β”€ store/
β”‚   β”œβ”€β”€ auth/           // User session, tokens
β”‚   β”‚   β”œβ”€β”€ AuthContext.jsx
β”‚   β”‚   └── useAuth.js
β”‚   β”œβ”€β”€ cart/           // Shopping cart (if applicable)
β”‚   β”‚   └── useCartStore.js  // Zustand
β”‚   β”œβ”€β”€ theme/          // Dark/light mode
β”‚   β”‚   └── ThemeContext.jsx
β”‚   └── ui/             // Modals, sidebars, toasts
β”‚       └── useUIStore.js

πŸ”§ Integration Points

Data Source State Layer
Laravel API Auth tokens in Context, fetched data in React Query
Hygraph CMS CMS content cached by React Query, UI state local
Local Storage Persisted Zustand store (theme, preferences)

The State Decision Tree

Is this state...
β”‚
β”œβ”€β†’ Used by 1-2 nearby components?
β”‚   └─→ useState + prop drilling βœ“
β”‚
β”œβ”€β†’ Complex with many actions?
β”‚   └─→ useReducer βœ“
β”‚
β”œβ”€β†’ Needed by distant components?
β”‚   β”œβ”€β†’ Small/simple? β†’ Context βœ“
β”‚   └─→ Large/complex? β†’ Zustand/Redux βœ“
β”‚
└─→ From a server?
    └─→ React Query (next sprint) βœ“

πŸŽ“ Methodology: Atelier Practice

The Sprint Rhythm

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ DAY 1: Context & Reducers                               β”‚
β”‚   β€’ Build AuthContext together (login/logout/user)      β”‚
β”‚   β€’ Practice: Refactor a complex useState to useReducer β”‚
β”‚   β€’ Discussion: When does local state become global?    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ DAY 2: Zustand Workshop                                 β”‚
β”‚   β€’ Live coding: Create a cart store with Zustand       β”‚
β”‚   β€’ Teams: Implement 1-2 stores for your app's domains  β”‚
β”‚   β€’ AI Practice: Generate actions/selectors             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ DAY 3: Architecture Review                              β”‚
β”‚   β€’ Each team presents their state architecture         β”‚
β”‚   β€’ Peer critique: Is this over-engineered? Under?      β”‚
β”‚   β€’ Refactor based on feedback                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

AI-Assisted Development Protocol

Task AI Role Your Role
Design state shape Propose structure Evaluate for your domain
Generate reducer actions Scaffold switch cases Ensure immutability
Debug context re-renders Explain the problem Apply memoization
Compare libraries List pros/cons Decide for your project

πŸ“ Sprint Deliverables

  • AuthContext with login/logout/user state
  • 1 Zustand store for a feature (cart, preferences, etc.)
  • useReducer for at least one complex component
  • State architecture diagram in your README
  • Persistence to localStorage for at least one store
  • Reflection: What patterns emerged? What would you change?

πŸ”— Lesson Navigation

Previous Current Next
Hooks Mastery State Architecture Routing

πŸ“š Key Concepts Preview

The State Locality Principle

Keep state as close as possible to where it’s used. Move it β€œup” only when:

  • multiple siblings need it
  • you must persist/share it
  • URL needs to represent it

Three tools, three jobs

  • useReducer: complex local transitions (FSM-like)
  • Context: dependency injection for shared state
  • Store (Zustand/Redux): shared state with selectors + devtools

Example: model state transitions explicitly

// Action shape: { type: 'ADD', id } | { type: 'REMOVE', id } | { type: 'CLEAR' }

Reflection (Atelier)

πŸ’­ Which state did you move too early? What complexity did it add?

πŸ’­ What invariant should your global state always respect?

Koan

β€œIf your state has no home, it will haunt every component.”


β€œThe best architecture is the simplest one that solves your problem. No simpler, no more complex.”