fluxury

For the impatient:
npm install --save fluxury
import {dispatch, createActions, createStore} from 'fluxury'
Why another "Flux framework"?
This is Flux plus 3 new "sugar" functions to guide you into the (state, action) -> state
pattern.
In flux@2.1, Facebook added 3 new abstract ES 2015 classes (FluxMapStore -> FluxReduceStore -> FluxStore). These stores guide you into the reducer pattern but, unfortunately, they also lead you into classes. This library reimplements the FluxStore in Douglas Crockford's class-free object oriented programming style.
This library is similar to Reflux and Redux except that this library doesn't try to replace the dispatcher with a new implementation. The library encourages you into simple patterns but doesn't try to change the core concepts. The flux/Dispatcher and fbemitter/EventEmitter modules are the key to Flux and this project depends directly on Facebook's implementations.
This new "Flux framework" adds a surface area of 3 new functions:
- dispatch
- createActions
- createStores
Don't be afraid to read the code. It is sparse 55 lines of ES 2015 code.
Pull requests welcome. Enjoy!
API
Submit an action into the stores. You must specify the type and, optionally, some data.
```js
import {dispatch} from 'fluxury';
dispatch('REQUEST_SETTINGS')
// or with data
dispatch('LOAD_SETTINGS', { a: 1, b: 2 })
```
2. createActions(action1, action2, ..., actionN)
Create your actions from a list of strings as `arguments`.
_MyActions.js_
```js
import {createActions} from 'fluxury';
export default createActions('INC', 'DEC', 'SET')
```
This returns a key mirrored object. The key and the value are equal. It is a useful JS hack.
```js
{
INC: 'INC',
DEC: 'DEC',
SET: 'SET'
}
```
To use the action in a React component:
```js
import {INC} from './MyActions'
var React = require('react');
var {dispatch} = require('fluxury');
var PropTypes = React.PropTypes;
var MyComponent = React.createClass({
handleClick: function() {
/* Call dispatch to submit the action to the stores */
dispatch(INC)
},
render: function() {
return (
<button onClick={this.handleClick}>+1</button>
);
}
});
module.exports = MyComponent;
```
3. createStore(name, initialState, reducer[ , queries, waitFor])
Create a new store with a name, initialState, reducer and optionally an object with queries and an array with dispatch tokens sent to waitFor.
```js
import {INC} from './MyActions';
import {createStore} from 'fluxury';
export default createStore('CountStore', 0, function(state, action) {
if (action.type === INC) {
return state + 1;
}
return state;
}, {
getCount: (state) => state // state is the count itself!
});
```
Perhaps you prefer the classic switch case form:
```js
import {INC} from './MyActions'
import {createStore} from 'fluxury';
export default createStore('CountStore', 0, (state, action) => {
switch (action.type)
case INC:
return state + 1;
default:
return state;
})
```
In this example you can make them both disappear:
```js
import {INC} from './MyActions'
import {createStore} from 'fluxury';
export default createStore('CountStore', 0, function(state, action) {
return state + (action.type === INC ? 1 : 0);
})
```
Store Properties and Methods
name | The name supplied when creating the store |
dispatchToken | A number used with waitFor |
addListener | A function to add a callback for events |
getState | A function that returns the current state |
Put it all together
var React = require('react');
var {dispatch, createStore, createActions} = require('fluxury');
var {INC, DEC} = createActions('INC', 'DEC');
var countStore = createStore('CountStore', 0, function(state, action) {
switch (action.type) {
case INC:
return state+1;
case DEC:
return state-1;
default:
return state;
}
});
var MyComponent = React.createClass({
componentDidMount: function() {
this.token = countStore.addListener( this.handleStoreChange );
},
componentWillUnmount: function() {
this.token.remove();
},
handleStoreChange: function() {
this.setState({ count: countStore.getState() })
},
handleUpClick: function() {
dispatch(INC)
},
handleDownClick: function() {
dispatch(DEC)
},
render: function() {
return (
<div>
<p>{this.state.count}</p>
<button onClick={this.handleUpClick}>+1</button>
<button onClick={this.handleDownClick}>-1</button>
</div>
);
}
});
module.exports = MyComponent;
MapStore Example
A simple store that accumulates data on each SET
action.
var {dispatch, createStore, createActions } = require('fluxury');
var {SET} = createActions('SET');
var store = createStore('MapStore', {}, function(state, action) {
switch (action.type) {
case SET:
return Object.assign({}, state, action.data)
default:
return state;
}
}, {
getState: (state) => state.states,
getPrograms: (state) => state.programs,
getSelectedState: (state) => state.selectedState
});
dispatch(SET, { states: ['CA', 'OR', 'WA'] })
dispatch(SET, { programs: [{ name: 'A', states: ['CA']}] })
dispatch(SET, { selectedState: 'CA' })
Example Applications
CSV File Viewer