The nanoflux high level API bases on factories, which provide all necessary components of the Flux architecture, i.e. Stores, Dispatcher, and Actions.
Returns the store, or undefined, if not exists.
createStore( name, descriptor )
Creates a store with given name and descriptor.
The descriptor is a JSON object containing the store’s available methods and members. Keep in mind, that nanoflux maps actions to store functions using the following convention: actionName > onActionName
var store = NanoFlux.createStore('myStore', {
__items : [],
// will be mapped to action name 'addItem'
onAddItem : function(item){
this.__items = this.__items.concat(Immutable(item));
this.notify();
}
});
Returns the dispatcher, or undefined if not exists. If name is null or undefined, the built-in default dispatcher will be returned.
createDispatcher( name?, actionList? )
Creates a dispatcher with given name and an optional action name list. Passing null or undefined, refers to the built-in default dispatcher. The actionList is an array of action names, that are going to be available as actions in the dispatcher (‘fluxy’):
Examples Adds some actions directly (‘fluxy way’) to the default dispatcher
var dispatcher = NanoFlux.createDispatcher(null,['addItem', 'loadItems']);
// usage example
dispatcher.addItem( item );
Creates a custom dispatcher.
var myDispatcher = NanoFlux.createDispatcher('myDispatcher');
Returns the action provider, or undefined if not exists.
createActions( name, dispatcher, actionDescriptor )
Creates actions with given name and descriptor using the given dispatcher. This is the typical way, as it offers full control of your actions. It is considered as best practice to access Web API (async calls) within the actions.
Keep in mind, that nanoflux maps actions to store functions using the following convention: actionName > onActionName
var dispatcher = NanoFlux.getDispatcher();
var myActions = NanoFlux.createActions('myActions', dispatcher, {
addItem : function(item){
// will be mapped to store function 'onAddItem'
this.dispatch('addItem', item);
},
loadItems : function(){
// async call - is a good practice to make web api calls on actions.
itemService.getAll().then( function(items){
this.dispatch('loadItems',items);
});
}
});
Adds a middleware function to the given dispatcher (or the default dispatcher if not given).
The function’s signature is fn(storeHandlerName, args)
, where storeHandlerName is the name of handler in
the targeted store, and args the payload.
function Logger(){
var log = [];
return function(handlerName, args){
log.push({
handler: handlerName,
payload : args
}
)
}
}
// somewhere in your app --- using the fluxy approach for sake of simplicity
// ...
var dispatcher = NanoFlux.createDispatcher(null, ["action1", "action2"]);
NanoFlux.use(new Logger(), dispatcher);
dispatcher.action1({foo:"fromAction1"});
/* Log is: [{handler: "onAction1", payload: [{foo:"fromAction1"}]}] */
dispatcher.action2({foo:"fromAction2"});
/* Final Log is:
[
{handler: "onAction1", payload: [{foo:"fromAction1"}]}
{handler: "onAction2", payload: [{foo:"fromAction2"}]}
]
*/
Each component of the Flux architecture provide additional methods, which are described here
Inside a store’s descriptor the following methods are available for every instance.
Within this method you can do some custom initialization on the store instance’s creation. A typical scenario would be the chaining of stores.
var store = NanoFlux.createStore('myStore', {
__items : [],
onAnotherStoreNotify: function(){
// called when 'anotherStore' executes 'notify'
}
onInitialization: function(){
var anotherStore = NanoFlux.getStore('anotherStore');
// chain the stores
anotherStore.subscribe(this, this.onAnotherStoreNotify);
},
onAddItem : function(item){
this.__items = this.__items.concat(Immutable(item));
this.notify();
}
});
Use notify to inform all subscribed views about state changes. Although, it is not common, it is possible to pass payload data as argument. Usually, a store maintains several states for certain context, that’s why payload won’t be passed on callback. But nanoflux is flexible enough to support even that.
var store = NanoFlux.createStore('myStore', {
__items : [],
// state getter
getItems : function(){
return this.__items;
},
onAddItem : function(item){
this.__items = this.__items.concat(Immutable(item));
this.notify();
}
});
var store = NanoFlux.createStore('myStore', {
__items : [],
onAddItem : function(item){
this.__items = this.__items.concat(Immutable(item));
// you may pass the state on callback
this.notify(this.__items);
}
});
subscribe( calleeContext, callbackFunc )
Creates a subscription and returns a subscription object. Once subscribed the subscriber callbackFunc is called on notify(). The calleeContext refers to the subscribers context and is bound to callbackFunc.
Use the returned subscription object to unsubscribe, e.g. while a component unmounts.
Note, that nanoflux offers the possibility to chain stores using subscribe (see onInitialization())
var MyComponent = React.createClass({
myStore : NanoFlux.getStore('myStore'),
getInitialState : function(){
return { subscription : null, items : [] }
},
// the callback from store
onStoreUpdated : function(){
// through calleeContext I can access this components methods
this.setState({ items : this.myStore.getItems() });
},
componentWillMount : function(){
// start listening to store when view is mounted
// passing calling context 'this' and the callback function
this.state.subscription = this.myStore.subscribe(this, this.onStoreUpdated);
},
componentWillUnmount : function(){
// unsubscribe
this.subscription.unsubscribe();
},
render(){
return (
// ... your render stuff
)
}
});
var store = NanoFlux.createStore('myStore', {
__items : [],
onAddItem : function(item){
this.__items = this.__items.concat(Immutable(item));
// you may pass the state on callback
this.notify(this.__items);
}
});
The Dispatcher is the central hub in a Flux architecture. nanoflux offers the possibility to use more than one dispatcher, if needed. Furthermore, with the nanoflux dispatcher you can attach simple, i.e. pure dispatch actions directly to the dispatcher, using a action name list on the dispatchers creation. This so called ‘fluxy’ approach, reduces boilerplate code significantly
var dispatcher = NanoFlux.createDispatcher(null,['addItem', 'loadItems']);
// usage
dispatcher.addItem(myItem);
dispatcher.loadItems();
connectTo(store|arrayOfStores)
Establish connection between a dispatcher instance and one or more stores. Once connected, the dispatcher is able to pass an action call towards its mapped store callback function.
Usually, multiple stores are connected to a single dispatcher, but it is also possible to connect one store to multiple dispatcher.
Tipp: Try to keep the setup as simple as possible, i.e. one dispatcher and several stores. Think twice, if you plan to introduce another dispatcher, or even chain a store.
var dispatcher = NanoFlux.createDispatcher(null,['addItem', 'loadItems']);
var myStore = NanoFlux.getStore('myStore');
var anotherStore = NanoFlux.getStore('anotherStore');
// usage example one dispatcher -> many stores
dispatcher.connectTo( [myStore,anotherStore] );
dispatch(actionName, payload?)
Executes a dispatch, and is usually called inside an action.
The actionName is used for the action-store-mapping. It is common, to use the same name as the function’s name. nanoflux maps actions to store functions using the following convention: actionName > onActionName. The payload will be passed as argument directly to the store’s method.
Usually, you won’t call this method directly, but use the Action Provider instead.
var dispatcher = NanoFlux.getDispatcher();
dispatcher.dispatch('actionName', {
foo: 1,
bar : "payload"
});
dispatch(actionName, payload?)
When using the conventional Flux approach (using the Action Provider Factory ) the created instance provides the Dispatcher.dispatch() function.
var dispatcher = NanoFlux.getDispatcher();
var myActions = NanoFlux.createActions('myActions', dispatcher, {
addItem : function(item){
// will be mapped to store function 'onAddItem'
this.dispatch('addItem', item);
},
loadItems : function(){
// async call - it is a good practice to make web api calls on actions.
itemService.getAll().then( function(items){
this.dispatch('loadItems',items);
});
}
});