Evolution of State Management
MedFrontend state management has evolved dramatically. From jQuery DOM manipulation to Redux to modern solutions like Zustand, each era solved problems while creating new ones. Understanding this history helps you choose the right tool.
Interactive Visualization
1
jQuery DOM
2006-2012The DOM was the state. Read from elements, write to elements. Simple but chaotic.
jQueryDOM manipulationEvent handlers
Example Code
// State = the DOM itself
// Read state from DOM, write state to DOM
$('#add-btn').click(function() {
// Read current count from DOM
var count = parseInt($('#counter').text());
// Update DOM directly
$('#counter').text(count + 1);
// Conditional UI updates
if (count + 1 > 10) {
$('#warning').show();
}
});
// State is scattered across DOM elements
// No single source of truth
// Hard to track what changed and whyProblems Solved
- Made DOM manipulation easy
- Cross-browser compatibility
- Simple for small apps
New Challenges
- State scattered across DOM
- No structure or patterns
- Spaghetti code at scale
- Hard to test or debug
These challenges led to: MVC / Backbone
1 / 7
Key Insight: The trend is toward simplicity. Modern solutions like Zustand prove you don't need complexity for predictable state.
Key Points
- jQuery DOM (2006): State lived in the DOM, read/write directly
- MVC/Backbone (2010): Separated models from views, event-driven
- Two-Way Binding (2012): Angular 1.x magic, but hard to debug
- Flux (2014): Unidirectional flow, actions → dispatcher → store
- Redux (2015): Single store, pure reducers, time-travel debugging
- Hooks + Context (2018): Built-in React, simpler but re-render issues
- Modern (2020+): Zustand, Jotai - minimal API, fine-grained updates
Code Examples
Era 1: jQuery DOM
// State = the DOM itself $('#add-btn').click(function() { var count = parseInt($('#counter').text()); $('#counter').text(count + 1); }); // No structure, state scattered everywhere
The DOM was the state. Simple but led to spaghetti code.
Era 2: MVC / Backbone
var Todo = Backbone.Model.extend({ defaults: { title: '', completed: false } }); var TodoView = Backbone.View.extend({ initialize: function() { this.listenTo(this.model, 'change', this.render); } });
Models as source of truth, views subscribe to changes.
Era 3: Redux
function todoReducer(state = [], action) { switch (action.type) { case 'ADD_TODO': return [...state, { text: action.text }]; default: return state; } } store.dispatch({ type: 'ADD_TODO', text: 'Learn Redux' });
Single store, pure reducers, predictable but verbose.
Era 4: Context + Hooks
const TodoContext = createContext(); function TodoProvider({ children }) { const [todos, dispatch] = useReducer(reducer, []); return ( <TodoContext.Provider value={{ todos, dispatch }}> {children} </TodoContext.Provider> ); }
Built into React, no external library needed.
Era 5: Zustand (Modern)
const useTodoStore = create((set) => ({ todos: [], addTodo: (text) => set((state) => ({ todos: [...state.todos, { text }] })), })); // In component - just use the hook! const todos = useTodoStore((s) => s.todos);
Minimal API, fine-grained updates, no provider needed.
Common Mistakes
- Using Redux for simple apps (overkill)
- Storing derived state instead of computing it
- Not splitting Context to avoid unnecessary re-renders
- Mutating state directly instead of returning new objects
Interview Tips
- Explain trade-offs between different state solutions
- Know when Context is enough vs when you need Zustand/Redux
- Understand why immutability matters for React rendering
- Be ready to discuss fine-grained vs coarse-grained reactivity
- Know the difference between local, global, and server state