cheatsheets/flux.md

198 lines
3.5 KiB
Markdown

---
title: Flux architecture
category: React
---
## About
### About
{: .-intro}
Flux is an architecture for building client-side web applications.
* [In-Depth Overview](https://facebook.github.io/flux/docs/in-depth-overview/) _(facebook.github.io)_
### Architecture
* __Dispatchers__ receive *actions* that get dispatched to its listeners.
* __Stores__ are objects that store data, usually changed from a dispatcher listener.
* __Views__ are React components that listen to Store changes, or emit *actions* to the dispatcher.
----
## Dispatcher
### Pub-sub
[A dispatcher][dispatcher] emits events (`.dispatch()`) to its listeners (`.register(fn)`).
```js
var Dispatcher = require('flux').Dispatcher;
d = new Dispatcher();
// send
d.dispatch({ action: 'edit', ... };
// receive
token = d.register(function (payload) {
payload.action === 'edit'
})
```
### Ensuring proper order
With multiple listeners, you can ensure one is fired after another using `.waitFor()`.
```js
token1 = d.register(...);
token2 = d.register(function (payload) {
// ensure receiver 1 is fired before this
d.waitFor([ token1 ]);
// process here
})
```
### Subclassing
[Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) is the preferred way to subclass Dispatcher (think `$.extend`).<br>
You can also make *action creators*, which are shortcuts for `dispatch()`.
```js
var Dispatcher = require('flux').Dispatcher;
var assign = require('object-assign');
var AppDispatcher = assign({}, Dispatcher.prototype, {
// action creator
handleViewAction(action) {
this.dispatch({
source: 'VIEW_ACTION',
action: action
})
}
})
```
----
## Stores
### Plain objects
Stores are just like objects.
```js
var TodoStore = { list: [] };
```
### Events
Sometimes they're eventemitters, too. Usually it's used to emit `change` events for views to pick up.
```js
var TodoStore = assign({}, EventEmitter.prototype, {
...
});
TodoStore.emit('change');
TodoStore.on('change', function () { ... });
```
### Model logic
Logic can sometimes belong in stores.
```js
{
isAllActive() {
return this.list.every(item => item.active);
}
}
```
----
## Stores and dispatchers
### Instantiate
Make a Dispatcher and Stores.
```js
d = new Dispatcher();
TabStore = { tab: 'home' };
```
### Updating data
Dispatch events to alter the store.
```js
d.dispatch({ action: 'tab.change', tab: 'timeline' });
d.register(function (data) {
if (data.action === 'tab.change') {
TabStore.tab = data.tab;
}
});
```
----
## With Views
### Listen to dispatchers
Views (React Components) can listen to Dispatchers.
```js
var TodoApp = React.createClass({
componentDidMount() {
this.token = AppDispatcher.register((payload) => {
switch (payload.action) {
case 'tab.change':
this.render();
// ...
}
});
},
componentDidUnmount() {
AppDispatcher.unregister(this.token);
}
});
```
### Listen to Stores
Or to Stores's `change` events.
```js
{
componentDidMount() {
TodoStore.on('change', this.onChange);
},
componentDidUnmount() {
TodoState.removeListener('change', this.onChange);
},
onChange(data) {
// ...
}
}
```
----
### Also see
* [Dispatcher API][dispatcher]
* [React cheatsheet](react.html)
* [Dispatcher.js source](https://github.com/facebook/flux/blob/master/src/Dispatcher.js)
* [Flux-todomvc explanation](https://github.com/facebook/flux/tree/master/examples/flux-todomvc)
[dispatcher]: http://facebook.github.io/flux/docs/dispatcher.html