

Flux Application Architecture - sehr
http://facebook.github.io/react/docs/flux-overview.html

======
wingspan
From first-hand experience, I can say that React+Flux has scaled well to 8+
developers over 800+ JS files and ~60k lines of code in a large single page
app here at Facebook. I'm happy to answer any questions! Some things that
we've struggled with:

1\. All data should be kept in stores. You may have some local component
state, but it shouldn't be anything you want to persist if the component is
unmounted. We have tried using state several times, and always go back to
keeping it in singleton stores. It also works better with the action-
dispatcher pattern.

2\. Now all your data is in stores, but how do you get it into the specific
component that needs it? We started with large top level components which pull
all the data needed for their children, and pass it down through props. This
leads to a lot of cruft and irrelevant code in the intermediate components.
What we settled on, for the most part, is components declaring and fetching
the data they need themselves, except for some small, more generic components.
Since most of our data is fetched asynchronously and cached, we've created
mixins that make it easy to declare which data your component needs, and hook
the fetching and listening for updates into the lifecycle methods
(componentWillMount, etc).

3\. Actions don't have callbacks, as they are by design fire-and-forget. So if
you need to be notified when some item has finished being created, for
example, you need to listen for the follow up action that the CREATE action
fires (yeah, actions firing actions, a bit ugly). Even then, how do you know
that CREATE_COMPLETED action correlates to the CREATE that you fired, and not
another? Well, actions also come with a payload, so what we ended up doing was
passing a context object into the payload and plumbing it all the way down
into the CREATE_COMPLETED and CREATE_FAILED actions. Being really strict about
actions is a major reason why Flux has scaled well for us.

~~~
dustingetz
do you just not use react state at all then? I have a similar sized app as
you, we started off naively using state at various levels, over time we
refactored the state higher and higher, and now we are at the point where
_all_ the state is kept only at the root of the view hierarchy (we use
cursors). We're about one step away from lifting even that state out of react
and into a store layer that has no react dependencies.

~~~
modarts
> (we use cursors)

I'd love to hear some more about the design of your data store: are these
cursors basically paths to data? Are they similar to Om's concept of cursors?
[https://github.com/swannodette/om/wiki/Cursors](https://github.com/swannodette/om/wiki/Cursors)

~~~
dustingetz
Yes, like Om. Cursor is a read/write view of a subtree of an immutable tree.

[https://github.com/wingspan/wingspan-
cursor/blob/master/js/C...](https://github.com/wingspan/wingspan-
cursor/blob/master/js/Cursor.js)

------
lhorie
I really like this architecture - it's clearly based on lessons learned from
the same types of pains that I myself encountered w/ non-trivial jQuery, and
the unidirectional data flow makes it a lot easier to reason about the code.
It's very similar to what I'm doing with my own micro mvc framework Mithril (
[http://lhorie.github.io/mithril](http://lhorie.github.io/mithril) ).

One thing that raise my eyebrows about this article though is how says that
Flux eschews MVC, and then goes on to say that it has stores that are
"somewhat similar to a model", and "the dispatcher exposes a method that
allows a view to trigger a dispatch to the stores", which, as far as classic
MVC goes, is the exact definition of a controller. What they call controller-
view is, imho, just an implementation detail within the view layer: in classic
MVC, views were responsible for subscribing to model observables, or, as the
article puts it, it "listens for events that are broadcast by the stores that
it depends on".

When talking about this architecture with the Mithril community, I find that
referring back to the MVC pattern makes it even easier to reason about the
flow of data: it's basically M -> V -> C -> M ...

It's unfortunate that the general understanding of the MVC pattern became
misunderstood over the course of many frameworks. The whole point of design
patterns should be that we could just name them for people to "get" it, rather
than having to reinvent new ways of naming things and having everyone relearn
the nomenclature.

~~~
m0th87
Thanks for Mithril - we're experimenting with it vs react.js for production
use. There's a lot of very smart design decisions there expressed in very
terse code.

One thing that threw me off was startComputation() / endComputation(). It
seems you have to be explicit about when properties are being updated for
views to update. I worry this might be error-prone vs react.js - if you forget
an endComputation(), or an exception occurs outside of a try/finally, your
views will freeze forever, no?

~~~
lhorie
That topic was brought up here:

[https://github.com/lhorie/mithril.js/issues/68](https://github.com/lhorie/mithril.js/issues/68)

Generally, you only need to manually call start/endComputation when
integrating to 3rd party code that needs to update Mithril managed bindings.

In the latest release, I tweaked the rendering aggressiveness to allow redraws
after exceptions in event handlers, and I updated the docs wrt `try/finally`
blocks in integration scenarios.

One other thing people could do that I don't think should go in Mithril core
is to call m.redraw inside window.onerror.

Of course, I'm open to other suggestions, if you have any.

~~~
m0th87
At least in my application, views are always bound to either an `m.prop` or an
immutable value. What if you tracked when an `m.prop` was updated and queued
up a redraw automatically? Redraws would be rate-limited via
requestAnimationFrames/setTimeouts as usual.

I imagine this could have a significant performance impact, but don't know the
mithril internals well enough to say.

EDIT: Thinking about it, the virtual DOM must be re-constructed on every
redraw since the props aren't tied to a view. This probably wouldn't work well
then.

~~~
lhorie
The topic of side-effect incurring getter-setters was also brought up a few
times in various forms. I wrote about my thoughts on it here (
[https://github.com/lhorie/mithril.js/issues/78](https://github.com/lhorie/mithril.js/issues/78)
)

As far as redrawing impact goes, Mithril does rate-limiting, so even
attempting to subvert m.prop to force it to spam redraws should still perform
ok.

------
clarkevans
The functional flux/react architectural style is truly excellent. Over the
last few months, Andrey Popp implemented a declarative form engine using React
and it's much simpler to reason about than our older JQuery equivalent. Having
undo/redo emerge as an almost-free feature from this architecture is super
useful.

[http://prometheusresearch.github.io/react-
forms/](http://prometheusresearch.github.io/react-forms/)

~~~
jingc
Agreed, we found that property really nice too - optimistic updating and
rolling back on error were similarly easy

------
rdtsc
I don't know web client development very well.

I could figure out jQuery back in the day pretty easily.

Then we started using Angular and I have tried and tried to understand all its
concepts my brain just couldn't keep track of list of: dom transclusion,
scopes, controllers, directives, services, dependency injections and so on.
More experienced JS developers loved and had no problem picking it up.

But after watching a few videos about React.js and worked through tutorials, I
really started to understand better. I really like the concepts and how this
library is put together. So far this is looking really good.

------
OliverM
I like the approach to managing information flow that is outlined here, but
it's over-stating the case to say that lack of such control is a failing of
the Model-View-Controller architecture. There are patterns you're supposed to
use with MVC such as the 'V' pattern, where information flows from the views
via the controllers to the models, where the models update themselves, and
then update the controllers which then update the views. Visually it looks
like:

    
    
      View receives event-------\..../----views render new state
      Controllers handle event---\../--controllers mediate new state
      Models react to new data----\/--models update controllers
    

The Sproutcore javascript MVC framework espouses this, for example, and I'm
sure many other MVC frameworks do too.

I'd be _really_ interested to see how Flux would augment statecharts...

~~~
OliverM
I should have added - these are the only actions you can take at each level,
so no arbitrary updating of views when you're in the left-hand side of the
controller stage, for example. That stops the arbitrary circular information
flows cited in the flux introduction.

------
rattray
Video seems to start discussion of Flux just after the 10 minute mark.

Direct Link:
[http://youtu.be/nYkdrAPrdcw?t=10m21s](http://youtu.be/nYkdrAPrdcw?t=10m21s)

EDIT: So far, the video is much more helpful to me in terms of bringing the
concepts of Flux to life. Jing does a terrific job explaining in my opinion.

~~~
shaohua
Jing did an amazing job explaining Flux. She should do a lot of more of those
talks.

------
blktiger
Seems like the dispatcher is a more manual version of the Ember/Sproutcore
run-loop. The advantage I see to the run-loop is that it batches all UI
updates so they happen only once, where the dispatcher simply batches up model
changes to reduce the number of redraws. Maybe I didn't fully understand what
the dispatcher does though...

~~~
peterhunt
In this architecture the batching occurs at the seam between flux and react
(setState) which can be flushed with an arbitrary strategy (ie the default
react run loop, or famous, or your own etc)

------
frik
I intuitively designed a very similar architecture to Flux & React, last year.
It's a lightweight PHP+JS framework. (used in this pet project:
[http://www.youtube.com/watch?v=-Lta5xSj4mY](http://www.youtube.com/watch?v=-Lta5xSj4mY)
)

Is there a name for such a pattern?

~~~
porker
Is your framework available anywhere? I'd be curious to take a look.

~~~
frik
I will write a blog post about it in the next days.

------
sarhus
Someone in the video asked a question about how AngularJS compares against
Flux+React.

Anyone has a more detailed explanation?

~~~
grayrest
For a long explanation, Pete Hunt gave a talk [1] as the extended
justification for using React.

[1] [http://www.confreaks.com/videos/3221-mwjs-be-predictable-
not...](http://www.confreaks.com/videos/3221-mwjs-be-predictable-not-correct)

Flux is just Facebook's internal usage pattern. Doesn't really have an Angular
equivalent other than the somewhat nebulous Angular best practices.

~~~
pacala
Really good video. Made me clearly understand that React is Javascript as if
it were to natively support the spreadsheet / reactive programming model.
Update a cell, dependent cells / signals get updated automagically. The huge
upside is that cells / signals are plain JS values that can be composed using
plain JS functions, and all the JS tooling just works.

Technically, this is done by simply using an unique dirty bit, which triggers
the recomputation of the rendered scene. Which is fast enough in practice, and
even supports unchanged hints to reduce the costs of expensive DOM updates.

This is eerly similar to 3d scene rendering. The unchanged hints are the
equivalent of viewport clipping, though require more work from the coder to
setup right.

------
gbrits
Watching the video I heard the speaker say unit testing is rather easy, since
state is always sitting next to code in your components. This is great and
sounds logical: test different input states and check against expected /
consistent output.

What I'm wondering, given the unidirectional flow and the design of flux as a
whole: would Integration Testing be needed at all anymore?

I mean, there's no state outside of the component that could possibly
influence the component's consistency. Therefore, all needed testing could be
done by simply unit-testing all components in isolation.

That sounds pretty huge.

------
mmerickel
It seems you could just pass the stores into the components as data - that's
really what they represent. I'm not clear why this approach is eschewing that
basic principle in favor of singletons.

~~~
jingc
The stores contain the data, but they also include the logic for updating that
data. For example, a store of all the comments would also subscribe to events
for new comments and add them into the comment thread at the correct location.
We've found it more maintainable to keep the application logic for a set of
data and the data itself in one place rather than having a model that external
pieces can modify.

------
swah
Can this architecture implement the client-side offline update while network
is down? (User clicks a "Like", its marked as Liked even if network is
down...)

~~~
alisnic
This architecture describes how data affects presentation and vice versa. Your
question is a bit off, it involves implementation, not structure.

~~~
swah
Ok, I also don't quite understand if the Store has any relation to the server-
side database.

~~~
colinramsay
It's just a store. You could write your implementation to store the data
anywhere - localstorage, a REST service, the one in the example just keeps it
in memory as an array.

------
hamxiaoz
This looks good. I'm wondering has anyone combined react and meteor in a real
project?

------
bkurtz13
I would like to see a boilerplate example of this architecture, especially the
dispatcher.

~~~
dan15
There's a TodoMVC example that you might find helpful:
[http://facebook.github.io/react/docs/flux-todo-
list.html](http://facebook.github.io/react/docs/flux-todo-list.html)

It'd probably be worth having a barebones starter kit though.

