Nuclear.Reactor
var reactor = new Nuclear.Reactor(config)
// or
var reactor = Nuclear.Reactor(config)
Configuration Options
config.debug
Boolean - if true it will log the entire app state for every dispatch.
Reactor#dispatch(messageType, messagePayload)
Dispatches a message to all registered Stores. This process is done synchronously, all registered Store
s are passed this message and all components are re-evaluated (efficiently). After a dispatch, a Reactor will emit the new state on the reactor.changeEmitter
reactor.dispatch('addUser', { name: 'jordan' })
Reactor#batch(fn)
added in 1.1
Allows multiple dispatches within the fn
function before notifying any observers.
reactor.batch(function() {
reactor.dispatch('addUser', { name: 'jordan' })
reactor.dispatch('addUser', { name: 'james' })
})
// does a single notify to all observers
Reactor#evaluate(Getter | KeyPath)
Returns the immutable value for some KeyPath or Getter in the reactor state. Returns undefined
if a keyPath doesn't have a value.
reactor.evaluate(['users', 'active'])
reactor.evaluate([
['users', 'active'],
['filters', 'username'],
/**
* @param {Immutable.List} activeUsers
* @param {String} usernameFilter
* @return {Immutable.List}
*/
function(activeUsers, usernameFilter) {
return activeUsers.filter(function(user) {
return user.get('username').indexOf(usernameFilter) !== -1
}
},
])
Reactor#evaluateToJS(...keyPath, [transformFn])
Same as evaluate
but coerces the value to a plain JS before returning.
Reactor#observe(keyPathOrGetter, handlerFn)
Takes a getter or keyPath and calls the handlerFn with the evaluated value whenever the getter or keyPath changes.
Note: You cannot call flux.dispatch
within the handle function of a flux.observe
. This violates one of the fundamental design patterns in Flux architecture, which forbids cascading dispatches on the system which cause highly unpredictive systems.
reactor.observe([
['items']
function(items) {
console.log('items changed');
}
])
Reactor#serialize()
added in 1.1
Returns a plain JavaScript object representing the application state. By default this maps over all stores and returns toJS(storeState)
.
reactor.loadState(reactor.serialize())
Reactor#loadState( state )
added in 1.1
Takes a plain JavaScript object and merges into the reactor state, using store.deserialize
This can be useful if you need to load data already on the page.
reactor.loadState({
stringStore: 'bar',
listStore: [4,5,6],
})
Reactor#registerStores(stores)
stores
- an object of storeId => store instance
reactor.registerStores({
'threads': require('./stores/thread-store'),
'currentThreadID': require('./stores/current-thread-id-store'),
})
Reactor#reset()
Causes all stores to be reset to their initial state. Extremely useful for testing, just put a reactor.reset()
call in your afterEach
blocks.
Reactor#ReactMixin
Exposes the ReactMixin to do automatic data binding.
var ThreadSection = React.createClass({
mixins: [flux.ReactMixin],
getDataBindings() {
return {
threads: Chat.getters.threads,
unreadCount: Chat.getters.unreadCount,
currentThreadID: Chat.getters.currentThreadID,
}
},
render: function() {
var threadListItems = this.state.threads.map(thread => {
return (
<ThreadListItem
key={thread.get('threadID')}
thread={thread}
currentThreadID={this.state.currentThreadID}
/>
);
}, this);
var unread =
this.state.unreadCount === 0 ?
null :
<span>Unread threads: {this.state.unreadCount}</span>;
return (
<div className="thread-section">
<div className="thread-count">
{unread}
</div>
<ul className="thread-list">
{threadListItems}
</ul>
</div>
);
},
});
module.exports = new Nuclear.Store({
getInitialState: function() {
// method must return an immutable value for NuclearJS to take advantage of efficient equality checks
return toImmutable({})
},
initialize: function() {
// sets up action handlers via `this.on`
this.on('SOME_ACTION', function(state, payload) {
// action handler takes state + payload and returns new state
})
},
})
Store#getInitialState
Defines the starting state for a store. Must return an immutable value. By default it returns an Immutable.Map
Store#initialize
Responsible for setting up action handlers for the store using this.on(actionTypes, handlerFn)
Store#serialize
added in 1.1
Serialization method for the store's data, by default its implemented as `Nuclear.toJS' which converts ImmutableJS objects to plain JavaScript. This is overridable for your specific data needs.
// serializing an Immutable map while preserving numerical keys
Nuclear.Store({
// ...
serialize(state) {
if (!state) {
return state;
}
return state.entrySeq().toJS()
},
// ...
})
Store#deserialize
added in 1.1
Serialization method for the store's data, by default its implemented as `Nuclear.toImmutable' which converts plain JavaScript objects to ImmutableJS data structures. This is overridable for your specific data needs.
// deserializing an array of arrays [[1, 'one'], [2, 'two']] to an Immutable.Map
Nuclear.Store({
// ...
deserialize(state) {
return Immutable.Map(state)
},
// ...
})
NuclearJS comes with several utility functions that are exposed on the Nuclear
variable.
Nuclear.Immutable
Provides access to the ImmutableJS Immutable
object.
Nuclear.toImmutable(value)
Coerces a value to its immutable counterpart, can be called on any type safely. It will convert Objects to Immutable.Map
and Arrays to Immutable.List
.
Nuclear.toJS(value)
Will coerce an Immutable value to its mutable counterpart. Can be called on non-immutable values safely.
Nuclear.isImmutable(value)
: BooleanReturns true if the value is an ImmutableJS data structure.
Nuclear.isKeyPath(value)
: BooleanReturns true if the value is the format of a valid keyPath.
Nuclear.isGetter(value)
: BooleanReturns true if the value is the format of a valid getter.