-
Notifications
You must be signed in to change notification settings - Fork 0
Description
0.5.0 is gonna introduce a new api called createModule and it will also deprecate the NuclearModule() constructor in favor of this new api.
createModule api is the new api which will be used to create new nuclear-js modules. It introduces new type of module syntax, both in creation and after creation steps.
// modules/counter/index.js
// 0.4.0: Use `NuclearModule` constructor directly.
// All modules are anonymous (has no name)
import NuclearModule from 'nuclear-module'
export default CounterModule = NuclerModule({ stores, actions, getters })
// 0.5.0: Use `NuclearModule.createModule()` to create modules.
// All modules has a name.
import { createModule } from 'nuclear-module'
export default CounterModule = createModule('Counter', { stores, actions, getters })- How stores were written in the initial releases was very different than how they are being written as regular stores in the regular
nuclear-jsmodule, we were making extra assumptions:
// modules/counter/stores/CounterStore.js
// 0.4.0: special syntax introduced for nuclear-module
export default {
getInitialState() { return 0 },
handlers: [
{ type: 'INCREMENT', handler(state) { return state + 1 } },
{ type: 'DECREMENT', handler(state) { return state - 1 } }
]
}
// 0.5.0: regular store definition syntax
export default {
getInitialState() { return 0},
initialize() {
this.on('INCREMENT', (state) => state + 1)
this.on('DECREMENT', (state) => state - 1)
}
}- Full
reactorinstance were being injected into each action as first parameter. In0.5.0things are changing into a way that actions are now functions returning real actions. This is an easier and cleaner way to injectdispatchandevaluatefunctions to the actions. (actions SHOULD only use these 2 functions anyway, instead of passing the fullreactorinstance was already not necessary).
// modules/counter/actions.js
// 0.4.0: registered reactor instance is injected as first parameter to the actions.
export const increment = (reactor) => reactor.dispatch('INCREMENT')
// 0.5.0: instead of full reactor instance, only `dispatch` and `evaluate` functions will be injected.
// also the signature is changed to a function returning function
export const increment = ({ dispatch, evaluate }) => () => dispatch('INCREMENT')- There is no change on how you would create getters. Pass
gettersobject tocreateModule()function.
These are the differences on how modules are created in 0.5.0. There is also changes on how you would use the created modules as a result from createModule() function.
- Actions are exported as the same way:
counterModule.actions.increment() - Registered getters will be exported as functions that will evaluate real getters
// app.js
// 0.4.0
const counter = CounterModule(reactor)
counter.actions.increment()
// use module level exported getters.
reactor.evaluate(CounterModule.getters.count)
// => 1
// 0.5.0
const counter = CounterModule(reactor)
counter.actions.increment()
// We can still use module level exported getters
reactor.evaluate(CounterModule.getters.count)
// => 1
// 0.5.0 introduces instance level getters:
counter.getters.count()
// => 1
// instance level getters are functions, which accepts an optional transform function.
counter.getters.count(count => count * 5)
// => 5- Before
0.5.0nuclear-modulewasn't doing anything about observers, other than simply exporting registered getters. Starting from0.5.0created modules will haveobserversproperty which works very similar to howinstance level getterswork.
// 0.4.0: use module level getters
reactor.observe(CounterModule.getters.count, (count) => console.log('count changed: %s', count))
counter.actions.increment()
// => count changed: 1
// 0.5.0: still can use module level getters to bind observers
// use instance level `observers`
counter.observers.count(count => console.log('count changed: %s', count))
counter.actions.increment()
// => count changed: 1
// with React
counter.observers.count(count => React.render(<div>{count}</div>))Why?
Initial releases were POC, which was really simple (it was all written in ~3 hrs) which didn't cover most use cases (registering same stores multiple times, not really providing any convenience other than providing a more structural index.js for your modules, making assumptions about how stores can be registered) when writing real modules.
With 0.5.0 registered module instances will have all their needs exported (computing getter results without requiring reactor instance, binding observers without requiring reactor instance, dispatching actions without requiring reactor instance).
Removal of the need of a reactor actually opens up many doors, most importantly removal of the hard dependency of nuclear-js (Module constructor functions will now require an object which has 4 functions: dispatch, evaluate, and observe, registerStores):
interface NuclearModuleReactor {
dispatch(actionType: string, payload: object): void;
evaluate(getter: Getter): any;
observe(getter: Getter, handler: function): void;
registerStores(stores: object): void;
}Since any Nuclear.Reactor instances will satisfy this interface, passing down your app's reactor still work quite nicely. This also opens up really nice ways to integrate with other flux/data/etc. libraries, and their modules.
- We can compose a new
dispatchfunction usingdispatch middlewares. (Possibility to usereduxmiddlewares) - We can compose a new
registerStoresfunction usingregisterStores middlewares. (Possibility to usereduxreducers as stores) - We can compose a new
observefunction usingobserve middlewares. (Possibility to useRxJSobservables as instance level observers)
With this release we will have the ability to use 3rd party libraries components in our reactor modules easily. Any feedback is appreciated.