uflux - Another implementation for the Flux architecture for React apps that pushes minimalism far.
But also:
See API.md for full API documentation.
When used via npm/bower/browserify/webpack/etc:
import { Dispatcher, Store, connectToStores } from 'uflux'
Your application will be composed of:
A disptacher is simply an EventEmitter.
const App = new Dispatcher()
App.on('eventname', function () { ... })
App.emit('eventname')
App.emit('eventname', arg1, arg2)
A store is an object that keeps a state and listens to dispatcher events.
Create a new store using new Store(dispatcher, initialState, handlers).
It listens to events from the dispatcher and responds by updating the store's state.
Each handler is a pure function that takes in the state and returns the new
state—no mutation should be done here.
const ListStore = new Store(App, {
items: []
}, {
'list:add': function (state, item) {
return {
...state,
items: state.items.concat([ item ])
}
}
})
App.emit('list:add', '2')
ListStore.getState() /* { items: [2] } */
To fire an action, just emit directly on your main dispatcher. No need for action methods.
App.emit('list:add')
If you're firing within an event listener (such as in a store), you can use emitAfter() to make the event trigger after all other events have triggered.
const DiceStore = new Store(App, { }, {
'dice:roll': function (state) {
App.emitAfter('dice:refresh')
return { number: Math.floor(Math.random() * 6) + 1 }
}
})
You can connect a react Component to a store using connectToStores(). The
state of the store will be available as properties (this.props).
const ListView = React.createClass({
statics: {
getStores () {
return [ ListStore ]
},
getPropsFromStores() {
return ListStore.getState()
}
},
render () {
return <div>hi, {this.props.name}</div>
}
})
ListView = connectToStores(ListView)
You can emit events inside handlers. They will be fired after committing the new state to the store.
const ListStore = new Store(App, {
items: []
}, {
'list:add': function (state, item) {
if (state.locked) {
const err = new Error('List is locked')
App.emit('list:error', err)
return { ...state, error: err }
}
}
})
App.on('list:error', function (err) {
console.log(err.message) //=> "List is locked"
console.log(ListStore.getState().error.message) //=> "List is locked"
})
Create unit tests for stores by duplicating it and assigning it to a new dispatcher via .dup().
const ListStore = new Store(...)
const App = new Dispatcher()
const TestListStore = ListStore.dup(App)
App.emit('list:clear')
// ...will only be received by TestListStore, not ListStore.
See API.md for full API documentation.
Unresolved API questions:
<script src="https://cdn.rawgit.com/rstacruz/uflux/v0.8.0/dist/index.js"></script>
var Store = window.uflux.Store
var Dispatcher = window.uflux.Dispatcher
var connectToStores = window.uflux.connectToStores
Using Babel is recommended for JSX parsing and enabling ES2015 features.
--stage 0 is recommended, too, for rest spreading support ({ ...state, active: true })—a feature very useful for Stores.
This is built as a proof-of-concept and has not been battle-tested in a production setup.
uflux © 2015+, Rico Sta. Cruz. Released under the MIT License.
Authored and maintained by Rico Sta. Cruz with help from contributors (list).
ricostacruz.com · GitHub @rstacruz · Twitter @rstacruz