Modern React Architecture: Context, Reducers & Custom Hooks
Structuring maintainable React applications with deterministic state management patterns and zero external overhead.
Author: Somesh ChatterjeeTags: react, javascript, architecture, state-management
Modern React Architecture: Context, Reducers & Custom Hooks
When building complex interactive web applications—such as browser-based desktop simulations—managing UI state cleanly without external state bloat is essential.
The Power of useReducer + useContext
For window managers or complex multi-step interfaces, treating state transitions as discrete, dispatched action objects guarantees predictability.
// Action types as clear constants
const ACTIONS = {
OPEN_APP: 'OPEN_APP',
CLOSE_APP: 'CLOSE_APP',
FOCUS_APP: 'FOCUS_APP',
};
function windowReducer(state, action) {
switch (action.type) {
case ACTIONS.OPEN_APP:
return {
...state,
openWindows: { ...state.openWindows, [action.payload]: true },
focusedApp: action.payload,
};
case ACTIONS.CLOSE_APP:
return {
...state,
openWindows: { ...state.openWindows, [action.payload]: false },
};
default:
return state;
}
}
Encapsulating Logic in Custom Hooks
Consumers of the context should never need to know the internal action shapes. Providing semantic, ergonomic helper methods via custom hooks encapsulates details cleanly:
export function useWindowManager() {
const context = useContext(WindowManagerContext);
if (!context) {
throw new Error("useWindowManager must be used within WindowManagerProvider");
}
return context;
}
Architectural Rules for Long-Term Health
- One Component per File: Keeps modules focused and testable.
- Strict File Size Limits: Break components that exceed 500 lines into sub-components.
- No Magic Strings: Store actions, storage keys, and constants in dedicated configuration registries.