- Getting the Storefront object...
- Storefront Static API
- Storefront Manager API
manager.actions( methods:object )
manager.before( methods:object )
manager.createEvent( name:string )
manager.get( name:string )
manager.hasChanged()
manager.invoke( outletOrAction:string|object, ...params:any[] )
manager.notify( data:any )
manager.observes( storeOrName:string|object, methods:object )
manager.outlets( methods:object )
manager.waitFor( storeOrName:string|object )
- Storefront Instance API
- Custom Events
If you're using a CommonJS system (browserify/webpack):
var Storefront= require( 'storefront')
If you are using Bower, Storefront
is available as a global.
In theory, Require.js and/or AMD modules are supported as well -- But they're completely untested.
Settings object:
name | default | description |
---|---|---|
asyncDispatch |
true | Defer dispatching from action creator to nextTick. |
freezeInstance |
false | Use Object.freeze on instance after definition. |
logging |
false | Log all dispatches to the console. |
useRAF |
true | Batch top-level onChange event using requestAnimationFrame. |
verbose |
false | Prints warnings to console. |
singletonDispatcher |
false | Use a global dispatcher instead of a shared-runtime instance. |
Defines a store:
Storefront.define( 'StoreName', manager =>{
// Object keys sent to .actions() become action names
manager.actions({
actionName( action ) {
// action === {
// origin: 'StoreName',
// type: 'StoreName_actionName',
// payload: { params }
// }
// You can wait for other Stores to complete their
// dispatch handling like this:
manager.waitFor( 'OtherStore' )
// Or...
var otherStore= manager.get( 'OtherStore' )
manager.waitFor( otherStore )
// After you have changed your internal data
// structures, trigger change event
manager.hasChanged()
// If you want to send a notify event
manager.notify( 'A message.' )
}
})
// Create your own "Action Creators"
manager.before({
actionName( dispatch, params ) {
// dispatch() is auto-bound with the action name,
// 'StoreName_actionName' in this case.
// Just send the payload to the dispatcher:
dispatch({ params })
}
})
// Provide data accessor methods for public consumption
manager.outlets({
// Available on the storefront instance
getSomething() {}
})
// Listen to actions from other other stores
manager.observes( 'OtherStore', {
// Match the action name/mthod of other store
otherActionName( action ) {
// You can send the name of the store to wait for, or get
// an instance with: manager.get( 'OtherStore' )
manager.waitFor( 'OtherStore' )
}
})
})
Retrieves a defined store.
Storefront aggregates all defined stores' onChange events into a single top-level change event. By default, it will use requestAnimationFrame to schedule event delivery.
Stops listening to aggregated change event.
Returns a new Runtime (Storefront instance) configured with the same settings, but none of the store definitions.
The store builder function will be called with an instance of a Manager. This is what you'll use to define your store's API (actions, outlets, observations, etc.).
Define actions that this store will handle. "Action Creators" are automatically created and look like this:
stubbed_action_creator= ()=> {
var args= Array.prototype.slice.call( arguments ),
dispatch= args.shift()
if( args.length === 1 )
dispatch( args[ 0] )
else
dispatch( args )
}
Define custom "Action Creators."
Create a custom store event. See Custom Events, below.
Returns a store instance by name.
Trigger an onChange event. You need to call this whenever your store's internal data structures have changed.
Call an outlet or action method on the store instance.
Trigger a Notify event.
Listen for actions on other stores.
Properties specified are created on the store instance.
Sequences dispatching so that the store specified will have handled the action before this method returns.
In addition to the outlets and actions defined in stores, storefront instances also have these properties defined:
// Get a store instance by name...
var store= Storefront.get( "StoreName" )
The name of the store.
Listen for changes on store instance. Not batched.
Returns unsubscription function.
let stopListening= store.onChange( ()=> alert( 'bang' ) )
// When you're ready:
stopListening()
Stop listening for changes.
Listen for notifications.
Stop listening for notifications.
The token used by the Dispatcher. Primarily for internal use.
Storefront will automatically create an action stub for every method defined in the actions
block:
Storefront.define( 'Timer', mgr => {
const {actions, outlets, dataHasChanged} = mgr
let _timer = {
active: false,
started: null
}
// Just define the 'actions' and the actions will be auto-stubbed
actions({
start( action ) {
_timer.active = true
_timer.started = +new Date
dataHasChanged()
},
stop( action ) {
_timer.active = false
_timer.started = 0
dataHasChanged()
}
})
outlets({
duration() {
var now = +new Date
return now - _timer.started
}
})
})
To implement your own "Action Creators," use the before
block. It will be provided a dispatch
function as the first argument. That function is pre-bound to trigger the correct action, so you just call it with your payload.
This is the same Timer example store as above, only it intercepts the start
action and only dispatches it if the timer isn't already running.
Storefront.define( 'Timer', mgr => {
const {actions, outlets, dataHasChanged} = mgr
let _timer= {
active: false,
started: null
}
before({
start( dispatch ) {
if( _timer.active === false ) {
dispatch() // carry on
}
else {
console.log( "Timer already started!")
// dispatch isn't called!
}
}
})
actions({
start( action ) {
_timer.active = true
_timer.started = +new Date
dataHasChanged()
},
stop( action) {
_timer.active = false
_timer.started = 0
dataHasChanged()
}
})
outlets({
duration() {
var now = +new Date
return now - _timer.started
}
})
})
You can define custom events in your store by calling storeManager.createEvent( name )
. Once defined, store instances have onXXX and offXXX methods (where XXX is the event name). Example:
var store= Storefront.define( 'Hotkey', mgr => {
const emitHotkey= mgr.createEvent( 'hotkey' )
/// Somewhere in your code:
emitHotkey( params )
})
// Instances now have support for:
store.onHotkey( fn )
store.offHotkey( fn )
Storefront provides a helper mixin that will register store event listeners and automatically deregister them at the componentWillUnmount
lifecycle hook.
It creates the helper method: onStoreEvent( storeName, eventName, callback )
Usage:
React.createClass({
mixins: [ Storefront.util.eventHelperMixin ],
componentDidMount() {
this.onStoreEvent(
"Auth", // Store name or Store instance
"ValidationError", // Event name
this.onValidationError // Handler
)
}
})
The event helper mixin is a thin wrapper around:
A utility for managing event subscriptions. Use it in a class-based React component like this:
class MyComponent extends React.Component {
componentDidMount() {
this._subscriptions= Storefront.util.subscriptions()
.on( 'MyStore', 'notify', this.onStoreNotification.bind( this ))
}
componentWillUnmount() {
this._subscriptions.release()
}
onStoreNotification( notice ) {
// Do something with it here...
}
render() {
return (
<div></div>
)
}
}