cheatsheets/flux.md

198 lines
3.5 KiB
Markdown
Raw Permalink Normal View History

2015-02-25 18:46:18 +00:00
---
2015-11-24 05:06:06 +00:00
title: Flux architecture
2015-11-24 05:09:17 +00:00
category: React
2015-02-25 18:46:18 +00:00
---
## 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
2015-02-25 18:46:18 +00:00
* __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.
2015-02-25 18:49:04 +00:00
----
2015-02-25 18:46:18 +00:00
## Dispatcher
2015-02-25 19:14:59 +00:00
### Pub-sub
2015-02-25 18:59:18 +00:00
[A dispatcher][dispatcher] emits events (`.dispatch()`) to its listeners (`.register(fn)`).
2015-02-25 18:46:18 +00:00
```js
var Dispatcher = require('flux').Dispatcher;
2015-02-25 18:59:18 +00:00
d = new Dispatcher();
2015-02-25 18:46:18 +00:00
2015-02-25 19:09:45 +00:00
// send
d.dispatch({ action: 'edit', ... };
2015-02-25 18:46:18 +00:00
2015-02-25 19:09:45 +00:00
// receive
2015-02-25 18:46:18 +00:00
token = d.register(function (payload) {
2015-02-25 19:09:45 +00:00
payload.action === 'edit'
2015-02-25 18:46:18 +00:00
})
```
2015-02-25 18:59:18 +00:00
### Ensuring proper order
2015-02-25 18:46:18 +00:00
2015-02-25 19:09:45 +00:00
With multiple listeners, you can ensure one is fired after another using `.waitFor()`.
2015-02-25 18:46:18 +00:00
```js
token1 = d.register(...);
token2 = d.register(function (payload) {
2015-02-25 18:49:04 +00:00
2015-02-25 18:46:18 +00:00
// ensure receiver 1 is fired before this
2015-02-25 18:49:04 +00:00
d.waitFor([ token1 ]);
// process here
2015-02-25 18:46:18 +00:00
})
```
### Subclassing
2015-02-25 18:59:18 +00:00
[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>
2015-02-25 18:49:04 +00:00
You can also make *action creators*, which are shortcuts for `dispatch()`.
2015-02-25 18:46:18 +00:00
```js
var Dispatcher = require('flux').Dispatcher;
var assign = require('object-assign');
var AppDispatcher = assign({}, Dispatcher.prototype, {
2015-02-25 18:49:04 +00:00
// action creator
2015-02-25 18:59:18 +00:00
handleViewAction(action) {
2015-02-25 18:46:18 +00:00
this.dispatch({
source: 'VIEW_ACTION',
action: action
})
}
})
```
2015-02-25 18:49:04 +00:00
----
2015-02-25 18:46:18 +00:00
## Stores
2015-02-25 19:14:59 +00:00
### Plain objects
2015-02-25 18:46:18 +00:00
Stores are just like objects.
```js
2015-02-25 19:13:00 +00:00
var TodoStore = { list: [] };
2015-02-25 18:46:18 +00:00
```
2015-02-25 18:59:18 +00:00
### Events
2015-02-25 19:09:45 +00:00
Sometimes they're eventemitters, too. Usually it's used to emit `change` events for views to pick up.
2015-02-25 18:59:18 +00:00
```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);
}
}
```
2015-02-25 18:49:04 +00:00
----
2015-02-25 18:46:18 +00:00
## Stores and dispatchers
2015-02-25 19:15:46 +00:00
### Instantiate
2015-02-25 18:59:18 +00:00
Make a Dispatcher and Stores.
2015-02-25 18:46:18 +00:00
```js
d = new Dispatcher();
TabStore = { tab: 'home' };
```
2015-02-25 18:59:18 +00:00
### Updating data
Dispatch events to alter the store.
2015-02-25 18:46:18 +00:00
```js
2015-02-25 18:59:18 +00:00
d.dispatch({ action: 'tab.change', tab: 'timeline' });
2015-02-25 18:46:18 +00:00
d.register(function (data) {
2015-02-25 18:59:18 +00:00
if (data.action === 'tab.change') {
2015-02-25 18:46:18 +00:00
TabStore.tab = data.tab;
}
});
```
2015-02-25 18:49:04 +00:00
----
## With Views
2015-02-25 18:46:18 +00:00
2015-02-25 19:14:05 +00:00
### Listen to dispatchers
Views (React Components) can listen to Dispatchers.
2015-02-25 18:46:18 +00:00
```js
var TodoApp = React.createClass({
2015-02-25 18:59:18 +00:00
componentDidMount() {
2015-02-25 19:09:45 +00:00
this.token = AppDispatcher.register((payload) => {
2015-02-25 18:59:18 +00:00
switch (payload.action) {
case 'tab.change':
2015-02-25 19:09:45 +00:00
this.render();
2015-02-25 18:59:18 +00:00
// ...
}
});
2015-02-25 19:09:45 +00:00
},
componentDidUnmount() {
AppDispatcher.unregister(this.token);
2015-02-25 18:46:18 +00:00
}
2015-02-25 18:59:18 +00:00
2015-02-25 18:46:18 +00:00
});
```
2015-02-25 19:14:05 +00:00
### Listen to Stores
Or to Stores's `change` events.
2015-02-25 19:09:45 +00:00
```js
{
componentDidMount() {
TodoStore.on('change', this.onChange);
},
componentDidUnmount() {
TodoState.removeListener('change', this.onChange);
},
onChange(data) {
// ...
}
}
```
2015-02-25 18:49:04 +00:00
----
2015-02-25 18:46:18 +00:00
### Also see
2015-02-25 18:59:18 +00:00
* [Dispatcher API][dispatcher]
* [React cheatsheet](react.html)
2015-02-25 19:09:45 +00:00
* [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)
2015-02-25 18:59:18 +00:00
2015-11-24 05:06:06 +00:00
[dispatcher]: http://facebook.github.io/flux/docs/dispatcher.html