| In your typical React component, you'll keep state in the parent, and pass them down as props to the children's subtrees. You also have to pass down handlers (`handleNameChange` for example) along with the props so that the child components can change the state. These handlers travel back to the parent, modify the state there, which triggers a re-render, and that travels from the parent down all the way to all the children again. This works for most use cases. This however forces you to keep all your model logic (computation, transformation, validation and server-communication) in the parent view component. So you'll extract a Model out of it, in which you keep all this data and logic. All the handler methods in the parent component would then call the mutation methods in this model instead of changing the component state directly. But now you need to ensure that the component state is consistent with the model state, for which you hook into the Model's onChange callback in the component's `componentDidMount` method. This means whenever the Model mutates, the component state changes accordingly. For example, if you have a `setPageTitle` method in the Store (that's what we call our Models in Flux), the store would mutate the value when `setPageTitle` is invoked, and call its own `emitChange` method, which triggers the `onChange` callback on the component which was registered during its `componentDidMount`. See: https://github.com/facebook/flux/blob/master/examples/flux-c.... You use EventEmitter (I prefer EventEmitter3) on the Store to make it an observable. See: https://github.com/facebook/flux/blob/master/examples/flux-c.... The first step in Flux is this: a simple View-Model separation using an EventEmitter store. Apart from the View-Model separation, this lets you share global state between multiple components. (Global state is bad for programmers, but the real world doesn't care. There are instances where you need to share the same data between multiple components and have them all update automatically) In the ThreadStore example I linked to above, the `emitChange` method is called only through the Dispatcher at the bottom. This is the next step: we do not let any component modify the store values directly. Everything is channeled through a uni-directional dispatcher. The reason to do this is to avoid one Store talking to another Store talking to another, and each of these causing cascading state changes in the components that observe them. So instead of having multiple intertwined paths to the Store, you force the entire application to go through a single-channel dispatcher that process each Action in sequence. The Actions are simply constants that are available globally to invoke specific behaviour across one or many stores. Each Store watches out for the Actions (a constant pushed into its mesage bus) they are interested in, and calls the appropriate method in its body. You push the Actions into the dispatcher, who is responsible for sending it to each Store. The dispatcher uses the same EventEmitter observable pattern to bind each Store to the actions they are interested in. Written in a hurry, but I hope it helps. The flux-chat repo (https://github.com/facebook/flux/blob/master/examples/flux-c...) is a great place to understand the entire pattern. |