Background
So far one of the most common architectural patterns that have been used in the we has been MVC.
Though MVC has been used for last couple of decades, with the new highly interactive websites/apps it doesn’t scale that well.
With the increasing number of model and views the relation between them no longer remains one to one and it sort of becomes like a web.
Introduction to flux
Flux simplifies it by providing more of a single directional data flow. This avoids a lot of the arrows that go into both directions.
What we have here is
- Action action corresponds to some action occurring on the UI.
- Dispatcher is sort of the central traffic controller to the application
- Store which maintains the data for the application
- View the view which is shown to the user and that re-render whenever the data changes in the store
When ever anything now happens on the View then then create a new action and give it to the dispatcher. Dispatcher makes sure that there are no cascading effects, which means that dispatcher accepts the next action after it has finished processing the store for the current action. And this is the biggest difference between MVC and Flux.
The simplicity we get by using Flux is because flow is just in one direction.
A more general view of Flux looks like this
In MVC model its very difficult to have a simplified view like above for a complex application
In flux, now the logic for updating of the data lives closer to the data store
Key code snippets of a Flux app
Registering your component with Store
componentDidMount: function(){
todoStore.addChangeListener(this._onChange);
}
_onChange: function(){
this.setState({
list: todoStore.getList()
})
}
Actions
var AppDispatcher = require('../dispatcher/AppDispatcher');
var todoActions = {
addItem: function(item){
AppDispatcher.handleAction({
actionType: appConstants.ADD_ITEM,
data: item
});
}
}
Constant
var appConstants = {
ADD_ITEM: "ADD_ITEM",
REMOVE_ITEM: "REMOVE_ITEM"
};
Dispatcher
var Dispatcher = require('flux').Dispatcher;
var AppDispatcher = new Dispatcher();
AppDispatcher.handleAction = function(action){
this.dispatch({
source: 'VIEW_ACTION',
action: action
});
};
Store - store has four parts
The actual “model” or data store
var _store = {
list: []
};
Setter methods
var addItem = function(item){
_store.list.push(item);
};
var removeItem = function(index){
_store.list.splice(index, 1);
}
The Store itself
var todoStore = objectAssign({}, EventEmitter.prototype, {
addChangeListener: function(cb){
this.on(CHANGE_EVENT, cb);
},
removeChangeListener: function(cb){
this.removeListener(CHANGE_EVENT, cb);
},
getList: function(){
return _store.list;
},
});
Action handlers
AppDispatcher.register(function(payload){
var action = payload.action;
switch(action.actionType){
case appConstants.ADD_ITEM:
addItem(action.data);
todoStore.emit(CHANGE_EVENT);
break;
case appConstants.REMOVE_ITEM:
removeItem(action.data);
todoStore.emit(CHANGE_EVENT);
break;
default:
return true;
}
});