Flux

State is a big problem in the UI. Most JS applications have few restrictions on how state is changed. This makes it difficult to understand why something happens. Anyone who's spent late nights trying to understand why their application suddenly stopped working after removing an innocuous line should understand this.

Flux is an answer to that problem. At its most basic level it's a set of rules about how to manage your applications state. Specifically who can change it, where they can change it and in what direction those changes should be propagated through your application.

There are 4 things you will need to understand: How to tell the application to change its state (Action creators), How to change the applications state (Stores), how to tell the view that the state has changed (State mixins) and how to tie them all together (Constants).

Action Creators are where any changes to your applications state starts. Actions are functions that are responsible for coordinating changes to local and remote state. Actions have a type which is a string describing the action (e.g. "UPDATE_USER_EMAIL").

We want to be explicit about the action types in your application so we define them as (Constants). Constants allow you to loosely couple your application as well as documenting what actions are available (Useful for understanding what your application can do). Constants are also responsible for creating action creators.

var UserConstants = Marty.createConstants(["UPDATE_USER_EMAIL"]);

var UserActionCreators = Marty.createActionCreators({
  updateUserEmail: function (userId, email) {
    this.dispatch(UserConstants.UPDATE_USER_EMAIL, userId, email);
  }
});

var app = new Marty.Application();

app.register('userActionCreators', UserActionCreators);
app.userActionCreators.updateUserEmail(122, "foo@bar.com");
var UserConstants = Marty.createConstants(["UPDATE_USER_EMAIL"]);

class UserActionCreators extends Marty.ActionCreators {
  updateUserEmail(userId, email) {
    this.dispatch(UserConstants.UPDATE_USER_EMAIL, userId, email);
  }
}

var app = new Marty.Application();

app.register('userActionCreators', UserActionCreators);
app.userActionCreators.updateUserEmail(122, "foo@bar.com");

In the above scenario, UserConstants.UPDATE_USER_EMAIL creates an action creator which, when invoked, will create an action with type UPDATE_USER_EMAIL.

If an action is making a change to your local state then it can pass its type data along to something called a dispatcher. The dispatcher is a just a big registry of callbacks (similar to an event emitter). Anyone interested can register to be notified when an action is dispatched.

var app = new Marty.Application();

app.dispatcher.register(function (action) {
  console.log('action with type', action.type, 'has been dispatched') ;
});

app.dispatcher.dispatchAction({
  type: 'foo'
});
Normally you don't manually register callbacks with the dispatcher, instead you create stores which do this for you. Stores hold information about a domain. That domain could be a collection of entities (Like a [Backbone Collection](http://backbonejs.org/#Collection)) or it could be some information about something specific (Like a [Backbone Model](http://backbonejs.org/#Model)).
var UserStore = Marty.createStore({
  handlers: {
    updateEmail: UserConstants.UPDATE_USER_EMAIL
  },
  getInitialState: function () {
    return {};
  },
  getUser: function (userId) {
    return this.state[userId];
  },
  updateEmail: function (userId, email) {
    this.state[userId].email = email;
    this.hasChanged();
  }
});
class UserStore extends Marty.Store {
  constructor(options) {
    super(options);
    this.state = {};
    this.handlers = {
      updateEmail: UserConstants.UPDATE_USER_EMAIL
    };
  }
  getUser(userId) {
    return this.state[userId];
  }
  updateEmail(userId, email) {
    this.state[userId].email = email;
    this.hasChanged();
  }
}

When your application starts, each store automatically starts listening to the dispatcher. When an action is dispatched, each store checks its handlers hash to see if the store has a handler for the actions type. If it does it will call that handler, passing in the actions data. The action handler then updates its internal state (all stored in this.state).

The next (and final) step is to notify views about the new data. Like the dispatcher, you can register to be notified of any changes to a store.

this.app.userStore.addChangeListener(function (state) {
  console.log('User store has changed', state);
});
If you have a view that's interested in a domain, it can ask the store to notify it of any changes. When the store updates, your view just rerenders itself with the new state. You might ask, "what if the store changed something your view isn't interested in (e.g. a different entity)?". Thanks to React's virtual DOM it doesn't really matter, if the state is the same then the view just returns the same DOM tree and React does nothing. This makes your views *significantly simpler* since you just render whatever the store tells you to render.
var User = React.createClass({
  contextTypes: Marty.contextTypes,
  render: function () {
    return (
      <div className="user">
        <input type="text"
               onChange={this.updateEmail}
               value={this.state.user.email}></input>
      </div>
    );
  },
  updateEmail: function (e) {
    var email = e.target.value;
    var userActions = this.context.app.userActionCreators;

    userActions.updateUserEmail(this.props.userId, email);
  }
  getInitialState: function () {
    var userStore = this.context.app.userStore;

    return {
      user: userStore.getUser(this.props.userId)
    };
  },
  componentDidMount: function () {
    var userStore = this.context.app.userStore;

    this.userStoreListener = userStore.addChangeListener(this.onUserStoreChanged);
  },
  componentWillUnmount: function (nextProps) {
    this.userStoreListener.dispose();
  },
  onUserStoreChanged: function () {
    var userStore = this.context.app.userStore;

    this.setState({
      user: userStore.getUser(this.props.userId)
    });
  }
});
class User extends React.Component {
  render() {
    return (
      <div className="user">
        <input type="text"
               onChange={this.updateEmail}
               value={this.state.user.email}></input>
      </div>
    );
  }
  updateEmail(e) {
    var email = e.target.value;
    var userActions = this.context.app.userActionCreators;

    userActions.updateUserEmail(this.props.userId, email);
  }
  getInitialState() {
    var userStore = this.context.app.userStore;

    return {
      user: userStore.getUser(this.props.userId)
    };
  }
  componentDidMount() {
    var userStore = this.context.app.userStore;

    this.userStoreListener = userStore.addChangeListener(this.onUserStoreChanged);
  }
  componentWillUnmount(nextProps) {
    this.userStoreListener.dispose();
  }
  onUserStoreChanged() {
    var userStore = this.context.app.userStore;

    this.setState({
      user: userStore.getUser(this.props.userId)
    });
  }
}

As your application grows you start to find that there is a lot of boilerplate code to get views to listen to stores. Containers are our solution to this problem. Containers manage listening to stores for you as well as providing a simpler API to implement:

var User = React.createClass({
  render: function () {
    return (
      <div className="user">
        <input type="text"
               onChange={this.updateEmail}
               value={this.props.user.email}></input>
      </div>
    );
  },
  updateEmail: function (e) {
    var email = e.target.value;

    this.app.userActionCreators.updateUserEmail(this.props.userId, email);
  }
});

module.exports = Marty.createContainer(User, {
  listenTo: 'userStore',
  fetch: {
    user() {
      return this.app.userStore.getUser(this.props.userId)
    }
  }
});
class User extends React.Component {
  render() {
    return (
      <div className="user">
        <input type="text"
               onChange={this.updateEmail}
               value={this.props.user.email}></input>
      </div>
    );
  }
  updateEmail(e) {
    var email = e.target.value;

    this.app.userActionCreators.updateUserEmail(this.props.userId, email);
  }
}

module.exports = Marty.createContainer(User, {
  listenTo: 'userStore',
  fetch: {
    user() {
      return this.app.userStore.getUser(this.props.userId)
    }
  }
});

Whenever you want to change a value within your application, your data must follow this flow of Action creator -> Dispatcher -> Store -> State mixin -> View. This is known as a unidirectional data flow.

Data flow

While this seems superfluous at first, it turns out to have some great benefits. First and foremost, it's really easy to debug. There's only one place your application state can change so you don't have to dig into all the views to work out where a value was changed (it's even easier if you're using immutable data collections). Thanks to action types being strings you have a loosely coupled Law of Demeter architecture which is easy to grow without increasing the complexity of the code base.