On Github tracker-common / redux-presentation
A sane approach to managing data flow in complex web applications
Web apps have become very complex.
"At some point you no longer know what happens in your app. You no longer control when, why, and how the state is updated."
Before talking about redux lets get some background.
Games have complex state that changes frequently based on simulations rules and user input.
Can we write web apps the way we write games?
Unlike other MV* frameworks since Backbone, React is a game changer because it lets us write web apps the way we write games. We can throw a new state at the DOM as often as we please.
This means we need to think about building applications differently.
(The UI is a side effect; your app should be able to run from the command line.)
How do we control data flow?
"Flux eschews MVC in favor of a unidirectional data flow"
Before:
After:
Unidirectional flow:
Stores hold your state Views listen to and render that state Events are represented as actions Actions get dispatched to the storesRedux is a pure, functional implementaiton of flux
(state, action) -> state
Redux doesn't have a Dispatcher or support many stores. Instead, there is just a single store with a single root reducing function.
As your app grows, instead of adding stores, you split the root reducer into smaller reducers independently operating on the different parts of the state tree.
By using only pure functions, everything is predictable
// The reducer function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + action.amount; case 'DECREMENT': return state - action.amount; default: return state; } } // The store bound with your reducer let store = Redux.createStore(counter);
// Side effects (this is where you could pass your data into react) store.subscribe(() => console.log(store.getState()) ); // Send some actions store.dispatch({ type: 'INCREMENT', amount: 1 }); // 1 store.dispatch({ type: 'INCREMENT', amount: 3 }); // 4 store.dispatch({ type: 'DECREMENT', amount: 2 }); // 2
More reasons:
Chainable dispatch plug-ins allowing you to inject behavior between receiving and action and processing it.
A useful place for side-effects - like logging... or making async requests!
Async flow:
When the ajax request returns: