Tiny (<100 SLOC), no-dependencies Flux implementation with store synchronization (waitFor) and Dependency Injection features
npm install geiger
Tiny (<100 SLOC), no-dependencies Flux implementation with store synchronization (waitFor) and Dependency Injection features.
Leverages React's (0.13+) contexts for injecting dependencies automatically down the component tree.
For a basic implementation reference, have a look at Idiomatic React.
For a full-scale implementation reference, making use of multiple synchronized stores, have a look at Idiomatic React Chat.
* Dependency injection: Services are injected in components, and so are relative to your application context, rather than being used as global services
* No dispatcher: rather than a central/global dispatcher, Geiger uses events and promises to manage the action flow, and to ensure that interdependent stores handle actions cooperatively
* Readable source code: the source code should be small enough to be readable, and so to serve as the primary source of documentation
``bash`
$ npm install --save geiger
`javascript
// main.js
'use strict';
import React from 'react/addons';
import { ContextFactory, Action, Store } from 'geiger';
import TodoList from './TodoList';
// The Context component (think "Dependency Injection Container")
const Context = ContextFactory({
todostore: React.PropTypes.object.isRequired,
todoactions: React.PropTypes.object.isRequired
});
// Actions; just relay to the store, but can be much thicker
const todoactions = new (class extends Action {
add(...args) { this.emit('add', ...args); }
remove(...args) { this.emit('remove', ...args); }
})();
// Store (Mutable)
const todostore = new (class extends Store {
constructor(actions, todos = []) {
super();
this.todos = todos;
// action handlers
this.listen(actions, 'add', (todo) => { this.todos.push(todo); this.changed(); });
}
// Public API
getAll() { return this.todos; }
})(todoactions, ['Todo One', 'Todo Two', 'Todo three']);
React.render(
(
todoactions={todoactions}
render={() =>
document.body
);
`
`javascript
//TodoList.js
'use strict';
import React from 'react/addons';
export default class TodoList extends React.Component {
// declaring dependencies to inject; can be a subset of all the context
static contextTypes = {
todostore: React.PropTypes.object.isRequired,
todoactions: React.PropTypes.object.isRequired
};
// watching store changes
componentWillMount() {
this.unwatch = [this.context.todostore.watch(this.forceUpdate.bind(this))];
}
// unwatching store changes
componentWillUnmount() { this.unwatch.map(cbk => cbk()); }
render() {
const { todostore, todoactions } = this.context;
return (
`
To synchronize store reaction to actions, use the waitFor() method of the store.
`javascript
'use strict';
import { Store } from 'geiger';
export default class StoreC extends Store {
constructor({ actions, storea, storeb }) {
super();
this.listen(actions, 'createTodo', (todo) => {
return this.waitFor([storea, storeb]).then(() => {
doSomething(todo);
});
});
}
}
`
In this example, waitFor() returns a promise that'll wait for all given stores to be idle, and that'll execute then when that happens. This promise has to be passed to Geiger (hence the return; this is asserted at runtime by Geiger, so no worries).
If you need to, you can waitFor() for stores that also waitFor() for other stores to complete their action handling.
```
$ npm test
MIT.
@netgusto