Architecture & State Store Design (Store Pattern)0%
Architecture & State Store Design (Store Pattern)
Beginner12 min read•Updated: Jul 11, 2026
Capstone Part 1: Architecture & State Store Design
In enterprise-scale frontend engineering, managing application state across dozens of decoupled components without prop-drilling or state divergence requires a centralized, predictable State Store Architecture. In this first capstone lesson, you will build a reactive, production-grade Store Engine implementing the Redux/Zustand pattern with immutable state updates, middleware pipelines, and subscriptions.
1. The Unidirectional Data Flow Architecture
Output
┌────────────────────────────────┐
│ UI Component (View) │
└───────────────┬────────────────┘
│ dispatch(action)
▼
┌────────────────────────────────┐
│ Middleware Pipeline │ (Logging, Crash Telemetry, Persistence)
└───────────────┬────────────────┘
│
▼
┌────────────────────────────────┐
│ Reducer Function │ (Pure function: (state, action) => newState)
└───────────────┬────────────────┘
│
▼
┌────────────────────────────────┐
│ Central Store State │
└───────────────┬────────────────┘
│ notify subscribers
▼
┌────────────────────────────────┐
│ Subscribed UI Components │ (Re-render with fresh selector data!)
└────────────────────────────────┘
2. Implementing the Store Core
JavaScript
class Store {
#state;
#reducer;
#subscribers = new Set();
#middlewares = [];
constructor(reducer, initialState, middlewares = []) {
this.#reducer = reducer;
this.#state = Object.freeze({ ...initialState });
this.#middlewares = middlewares;
}
// Read current state immutably
getState() {
return this.#state;
}
// Subscribe to state changes (returns unsubscribe function)
subscribe(listener) {
this.#subscribers.add(listener);
return () => this.#subscribers.delete(listener);
}
// Dispatch an action through middleware to the reducer
dispatch(action) {
if (!action || typeof action.type !== 'string') {
throw new TypeError('Actions must be objects with a string "type" property.');
}
// Execute middleware chain
const runMiddleware = (index) => {
if (index < this.#middlewares.length) {
const middleware = this.#middlewares[index];
middleware(this, action, () => runMiddleware(index + 1));
} else {
// Reducer execution after all middleware complete
const nextState = this.#reducer(this.#state, action);
this.#state = Object.freeze({ ...nextState });
// Notify all subscribers
this.#subscribers.forEach(listener => listener(this.#state));
}
};
runMiddleware(0);
}
}
3. Implementing Logging & LocalStorage Middleware
JavaScript
// Middleware 1: Action Logger
const loggerMiddleware = (store, action, next) => {
console.group(`[Action]: ${action.type}`);
console.log('Previous State:', store.getState());
console.log('Payload:', action.payload);
next(); // Pass to next middleware
console.log('Next State:', store.getState());
console.groupEnd();
};
// Middleware 2: Persistent Storage Sync
const storageSyncMiddleware = (store, action, next) => {
next(); // Run reducer first
localStorage.setItem('app_state_backup', JSON.stringify(store.getState()));
};
4. Reducer & Selectors
JavaScript
// Initial State
const initialAppState = {
user: { name: 'Elena', role: 'admin' },
notifications: [],
theme: 'dark'
};
// Pure Reducer Function
function appReducer(state, action) {
switch (action.type) {
case 'THEME_TOGGLE':
return { ...state, theme: state.theme === 'dark' ? 'light' : 'dark' };
case 'NOTIFICATION_ADD':
return {
...state,
notifications: [...state.notifications, action.payload]
};
case 'NOTIFICATION_CLEAR':
return { ...state, notifications: [] };
default:
return state;
}
}
// Selectors for targeted state queries
const selectTheme = state => state.theme;
const selectNotificationCount = state => state.notifications.length;
5. Usage & Verification
JavaScript
const store = new Store(appReducer, initialAppState, [loggerMiddleware, storageSyncMiddleware]);
// Subscribe component listener
const unsubscribe = store.subscribe((newState) => {
console.log('UI Render triggered! Current Theme:', selectTheme(newState));
});
// Dispatch actions
store.dispatch({ type: 'THEME_TOGGLE' });
store.dispatch({
type: 'NOTIFICATION_ADD',
payload: { id: 1, text: 'Backup completed successfully.' }
});
// Unsubscribe when component unmounts
unsubscribe();
Interactive Quiz
Practice Quiz
Question 1
What is the role of a Reducer in a unidirectional state store architecture?
Question 2
Why is the state object frozen with Object.freeze() inside the Store?
Question 3
What is the responsibility of Middleware in a state store?
Question 4
Why do store.subscribe() methods return an unsubscribe function?
Question 5
What is a "Selector" in modern state management?
Next Lesson
Real-Time Collaborative Dashboard Engine
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
Related Lessons
| Previous Lesson | Next Lesson |
|---|---|
| Asynchronous Iterators & Reactive Streams | Real-Time Collaborative Dashboard Engine |
Practice Quiz
Test your understanding of this lesson with 5 questions. Each question has one correct answer.