Flux
Problem
Bidirectional data flow creates unpredictable update cycles where views update models, models update other models, and the cascade becomes impossible to trace. State changes can come from anywhere, making bugs hard to reproduce. Multiple components directly mutating shared data leads to race conditions and inconsistent UI state across the application.
Solution
Unidirectional data flow where actions trigger state changes that flow down to views, which dispatch new actions. This creates predictable state management where updates follow a consistent pattern.
Example
This example demonstrates the Flux pattern with unidirectional data flow from actions through the dispatcher to stores.
// Action: Dispatched from views to trigger state changes
dispatcher.dispatch({ type: 'ADD_TODO', text: 'Learn Flux' });
// Store: Holds state and responds to actions
const store = { todos: [] };
// Register handler with dispatcher to update store based on actions
dispatcher.register((action) => {
// Check action type to determine how to update state
if (action.type === 'ADD_TODO') {
// Update store state
store.todos.push({ text: action.text });
// Notify views that state changed
emitChange();
}
});
Benefits
- Creates predictable unidirectional data flow
- Makes state changes traceable and debuggable
- Reduces complexity of bidirectional data binding
- Enables time-travel debugging and state replay
- Provides clear separation of concerns
Tradeoffs
- Adds boilerplate with actions, dispatchers, and stores
- Can feel over-engineered for simple applications
- Learning curve for developers new to the pattern
- Largely superseded by Redux and modern state management
- Requires more code to accomplish simple state updates