198 lines
3.5 KiB
Markdown
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
|