Flux
What is Flux
Flux is an architecture for handling data.
Characteristics:
- explicit and understandable update paths
- maintains a strict decoupling of components
- makes tracing changes during development simpler
- bugs are easier to track down and fix
The big picture




MVC pattern
Flux pattern
Problems with MVC
When more than one Controller modifies a Model:
- the dependency graph becomes harder to trace
- it's hard to debug when the models have dependencies
Flux architecture
Main components:
-
views
- are responsible for handling an action by a user
- send requests for data to the stores via the dispacher
-
dispatcher
- takes requests for actions from the views
- pass the requests to the pertinent store (or stores)
-
stores – store state
- wake up on a relevant dispatch to retrieve the requested data
- notify the views of changes
- actions – provide actions for the views
Problems with Flux
- no official architecture implementation
- Facebook only provides the dispacher
- lots of small competing implementations
- no clear unified way on how to deal with async actions
- no clear way of how to resolve dependency between stores
- dispatcher contains waitFor method
Flummox
Provides a clean implementation, that is ES6 compatible.
- doesn't rely on mixins
- doesn't use higher order components structure
- based on extending 3 classes Action, Store and Flux
Components:
- Action class
Actions
- we created a single action, createMessage
- the return value is sent through the dispatcher automatically
Async handling:
- if you return a Promise, Flummox will wait for the Promise to resolve and then dispatch the unwrapped value
- can also use the ES7 async-wait pattern
import { Actions } from 'flummox';
class MessageActions extends Actions {
createMessage(messageContent) {
return {
content: messageContent,
date: Date.now(),
};
}
}
Stores
import { Store } from 'flummox';
class MessageStore extends Store {
constructor(flux) {
super(); // Don't forget this step
const messageActionIds = flux.getActionIds('messages');
this.register(messageActionIds.createMessage, this.handleNewMessage);
this.state = {
messages: [],
};
}
handleNewMessage(message) {
this.setState({
messages: this.state.messages.concat([message]),
});
}
}
- set initial state by assigning to this.state in the constructor
- update state by using this.setState()
- a change event is emitted automatically whenever you call this.setState()
- emit events manually using this.emit()
Flux Class
import { Flux } from 'flummox';
class AppFlux extends Flux {
constructor() {
super();
this.createActions('messages', MessageActions);
// The extra argument(s) are passed to the MessageStore constructor
this.createStore('messages', MessageStore, this);
}
}
- unifies our stores and actions, along with a dispatcher, into a single, self-contained instance.
- registers the Actions and the Stores
- each instance has its own dispatcher
Use it in a view
import FluxComponent from 'flummox/component';
class MessagesView extends React.Component {
render() {
return (
<FluxComponent connectToStores={{
messages: store => ({
messages: store.messages
})
}}>
// MessageList is injected with a `messages` prop by FluxContainer
<MessageList />
</FluxComponent>
);
}
}<FluxComponent flux={flux}>
// Immediate children have flux prop
</FluxComponent>
<FluxComponent>
// Same as last time: immediate children have flux prop
// flux is already part of context, and remains so
</FluxComponent>
FluxComponent
FluxComponent:
- it uses the React context to expose the Flux instance to nested views
- makes it easy to subscribe to store updates
- the immediate children get the stores as properties
- so you don't have to explicitly pass properties down the component tree
- pass a flux instance as a prop to a FluxComponent near the top of your app hierarchy, any FluxComponents further down the tree will automatically have access to it
Access flux from context
class MyComponent extends React.Component {
constructor (props, context) {
super(props, context);
}
}
MyComponent.contextTypes = {
flux: React.PropTypes.object.isRequired
};<FluxComponent flux={flux}>
<App>
<MyComonent/>
</App>
</FluxComponent>- pass the context as the second param of the constructor
- define flux in the contextTypes of the React component
Final thoughts
- the maintainer of Flummox recommends using Redux instead
- Redux is less popular than Flummox 271 vs 1255 downloads
- we should consider it if
- plays nice with ES6 classes
- no mixins, no higher order components
Flux
By kenjiru
Flux
Flux & Flummox overview
- 671