
Flux Architecture Visual Cheatsheet - ihenvyr
http://danmaz74.me/2015/07/27/flux-architecture-visual-cheatsheet/
======
morley
This is a really great visual!

In my experience, the toughest thing to grasp about Flux was how to handle
async server actions. It's something that a lot of tutorials (including,
unfortunately, this graphic) handwaves, but it's one of the first things you
need to nail down if you want to do anything exciting in an SPA.

The todos usually make it seem like you have to to have this flow of
information:

ActionCreator -> ApiUtil -> ActionCreator -> Store

...but if you use the same action creator, you end up with a circular
dependency. So you actually have to create a separate file of
ServerActionCreators, that are only called with ApiUtils:

ViewActionCreator -> ApiUtil -> ServerActionCreator -> Store

This seems like a lot of boilerplate. At my job, we've simplified this a lot
by using Reflux, which has async actions that run one Store callback when a
call gets initiated, and another related one when it gets completed. But it's
not ideal.

Personally, I'd rather see a bigger app than a TodoMVC implementation with a
"correct" example of async server actions.

~~~
aggronn
There is some amount of boilerplate with rolling your own, but I think people
might benefit from rolling their own flux implementation when they first try
to play with react. The best solution I think for this is to have multiple
dispatches in your actions.

Create action -> action[dispatch 'action pending' -> async action -> dispatch
'action complete with data'] -> stores.

Keep your stores completely sync, and the data in a single object, and maybe
have them all be pure functions, and suddenly there is no web of anything and
theres a single source of truth, and bam. nice.

------
drb311
This flow chart explain things that are hard to grasp in words.

Dan Roam's Back of a Napkin is a good guide to thinking and communicating in
this visual way. You can get quite a long way with the freebies on his site,
but it's worth shelling out for the whole book.

[http://www.danroam.com/the-back-of-the-napkin/](http://www.danroam.com/the-
back-of-the-napkin/)

When I studied the diagram, I found myself running through an imaginary
scenario in my head. The Overview text makes it hard to do this. If you don't
create a diagram and want to explain a process clearly, don't explain the
components -- follow an example action through the process, and your readers
will grasp it much better.

------
yoklov
I used React+Flux for a level editor for a game recently. It seemed to me like
there was one or two too many levels of indirection.

Specifically, I'm not sure what problem the Dispatcher is actually solving. It
seems to just add boilerplate and indirection for little benefit.

~~~
danmaz74
The most popular library to implement Flux, reflux, actually does away with
the dispatcher. But during my research I read many posts showing that having
the dispatcher is actually a good idea; just off the top of my head: it makes
debugging easier, and it allows you to enforce the "waitFor" mechanism to
coordinate the update order of the different stores.

I even think it could also be used for one more goal.

With standard Flux, if an action updates multiple stores, and a
ModelController is dependent on those multiple stores, that ModelController
will get rendered (to the virtual DOM) multiple times, which is inefficient.

If instead the stores notified the dispatcher that they were updated, and then
it was the dispatcher to dispatch all the "change" events to the
ViewControllers only once (ie: if a ViewController is dependent on two
different stores, and they were both "changed", it would still only get one
"change" event) this would make those situations much more efficient.

------
polskibus
The problem here is the horizontal arrow between two stores. This leads to a
web of connections, the usual spaghetti of data binding. There should either
be a "store of stores" or another element that would direct the data flow so
that it is unidirectional.

If anyone knows about a flux implementation that solves this - I'd love to
hear about it!

~~~
sync
redux composes stores into one, and discourages the "web of connections":
[https://github.com/gaearon/redux](https://github.com/gaearon/redux)

It is rather immature, but we are using it in production without a problem,
and the API is stable as of the 1.0 RC.

~~~
nuschk
We're also using redux in production, after having switched from reflux. In
redux, it's so much more clear where to put stuff.

In reflux, it was never clear to us whether certain async server operations
should be handled in stores or in the actions. In general, you would always
want them to be with your actions. Though every time you need a store variable
to do the server call, you end up putting code in the store again (or passing
the needed state through your react components, which is even uglier).

Not so in redux, where you have access to the stores in your actions. This
way, stores get really dumb, which is the way they should be IMO.

And, btw, replacing reflux by redux is relatively easy and straightforward, as
the same general concepts (flux) apply.

I also find the redux code easier to read, as the whole library is doing less
(while achieving the same).

------
findjashua
If you're wondering about which flux implementation to start with, I'd highly
recommend checking out Redux :
[https://github.com/gaearon/redux](https://github.com/gaearon/redux)

The main idea is to think of stores as reducers (redux = reducers + flux). He
also gave a very good talk on it at react-europe:
[https://www.youtube.com/watch?v=xsSnOQynTHs](https://www.youtube.com/watch?v=xsSnOQynTHs)

~~~
dmix
Where is a good place for an experienced JS dev to start learning about
Flux/React without having prior exposure to either of them?

Any video/article recommendations?

I usually wait ~1yr before trying out any new JS library/framework and wait to
see if they stick around - given the constant hype machine that generates
them.

------
MPiccinato
This is great! We dove into React and Flux a few months ago and it took way
too long to come to the realization that this flowchart puts together.

One of the big things I think a lot of React/Flux tutorials miss out on are
the "Smart and Dumb" components. This was the missing "view controller" that I
am used to with MVC and the flowchart illustrates it nicely.

~~~
bdat
I totally missed the concept of having _high-level_ Controller-Views when I
first started playing around with React. Just understanding the concept is
only half the battle too; you have to have the self-control to keep lower-
level components immutable using props and pass in the 'state' via the higher-
level controller-views. Has anyone had experience with Flex and the Cairngorm
Framework (from back in the day)? I find Flux borrows heavily from its design.

------
hoverbear
The little "Tweet/etc this" box is so awesome, it actually half covers the
first letter of each line and follows you down the whole page! How user
friendly.

------
RobertoG
Somebody knows if the proposed library in the article, Alt, with ReactJs makes
a full solution (like AngularJs for instance)?

~~~
danmaz74
I'm not an expert about AngularJS and we're still studying/experimenting with
Alt, but AFAIK the combination is comparable, except maybe for the AJAX
communication with the server - if Angular also manages that (which I don't
know): with Alt you need to manage the server calls yourself, preferably by
creating some API helper functions and calling them from inside the Actions.

EDIT: clarification

~~~
RobertoG
Thanks for your answer.

Angular have a specific service ($http) for that.

~~~
danmaz74
You're welcome.

By the way, when I did my research, I found out that some people are using
React with Meteor, instead of Flux. That way, server synchronization should
become a non-issue (but you need to like the Meteor way).

------
danmaz74
OP here, if you have any questions/comments feel free to ask

~~~
burger_moon
What you did looks great, I just wish there was a way to download this. Maybe
I missed it but I couldn't find a way to save a local copy.

~~~
danmaz74
Glad you like it; I just added to the post a link to an exported PNG file -
it's uglier but I understand it can be useful. There you go:
[http://danmaz74.me/wp-content/uploads/2015/07/flux-
architect...](http://danmaz74.me/wp-content/uploads/2015/07/flux-architecture-
visual-cheatsheet-full.png)

PS just wished mural.ly allowed to export a PDF instead of a PNG

~~~
burger_moon
Yes I hoping there was a way to save it as a PDF. This will still be useful
however. Thank you.

I was just concerned about going back to the link in a couple months and
finding a dead url.

------
bradrydzewski
This is a really great intro. I like how it expands on the basic flux diagram
that I see everywhere.

One thing missing from many flux tutorials and sample applications that I
would love to see included is error handling. How do you manage errors in your
flux applications? Do you keep them in the store? If using something like
react-router, how do you ensure you flush errors from the store as your routes
change and they are no longer applicable to the data in view?

------
tomjen3
Holy fuck that javascript completely breaks me actually seeing that image, can
you just link straight to the .png?

Thanks.

~~~
danmaz74
You mean you can't see the "mural" on mural.ly? Because that's the original,
the PNG is only a low-res screenshot... I can export a high-res screenshot if
it would work better for you, but in general the mural is much better for
zooming.

~~~
dwaltrip
I could see the image on mural.ly, but it got stuck on a certain zoom level
(I'm using my android). Thanks for posting the high resolution png.

------
malandrew
This is actually all you really need to know about flux:

[https://twitter.com/substack/status/621818725159710720](https://twitter.com/substack/status/621818725159710720)

[https://twitter.com/substack/status/621832733564628992](https://twitter.com/substack/status/621832733564628992)

[https://twitter.com/substack/status/621639688919515136](https://twitter.com/substack/status/621639688919515136)

That first tweet succinctly explains flux in less than 140 characters.

At the end of the day, pretty much every react "best practice" I've seen
converges on approaches that raynos/mercury offer out-of-the-box.

React's decision to allow local state inside components was an "original sin"
and every single engineers that decides to author a library to make React/Flux
simpler is really just engineering around the poor decision of allowing local
state.

Have of those should, might, could update if they felt like it react class
props are unnecessary complexity that had to be bolted on to overcome issues
with local state.

Here's a better approach:

(1) components that are pure functions that take in state that they should
render. state hasn't changed? don't call the function

(2) components that have state that needs to be tracked can export a function
that produces an instance of the state that component consumes

(3) compose the state of the UI, by calling the state instantiating function
of all the components in your UI. Nest as appropriate.

(4) Make sure all these state instances are bijective lenses that keep one
source of truth for a certain state value. Everywhere that state is needed or
could be modified receives that "cursor" via dependency injection. The
simplest example demonstrating a state cursor is the raynos/observ library.

The composed state object is the waist of your app hourglass, just like IP is
the waist of the Internet. All I/O modifies state and that state propagates
from there. Anything rendered to the screen is the O in I/O. Any events coming
from your mouse or other peripheral is the I in I/O. Any syncing via XHR or
websockets can be the I and the O in I/O. All I/O flows to the state.

Anything that needs to react to changes in that state have two options:
subscribe to state change events (push) or read the current state as necessary
(pull).

This really isn't all that hard and React/Flux has overcomplicated things
immensely and given it a flashy name. The myriad libraries that purport to
make it easier and simpler are just overcompensating for something that
fundamentally needs to be re-engineered, but won't because it breaks backwards
compatibility and requires people to move state logic (read: business logic)
out of the component classes (that probably shouldn't have been there in the
first place).

~~~
TheAceOfHearts
I mostly agree, but I don't think you're entirely correct about component
local state.

I do flux and I keep everything in stores or some variation, and my components
take everything as props, so they're usually pure functions. However, for my
base (i.e. heavily reusable) components, I use local state to track ephemeral
component state. One such example, if I'm doing an animation when someone
clicks on an input, such as a material design textfield.

~~~
malandrew
That too is solvable by eliminating local state and has an advantage of making
animation time travel debugging possible.

So in my comment above I mentioned having a component export two functions.
One function is a pure render function and one function creates a state
instance. The state of the animation would be one of the things tracked in the
state instance:

    
    
        var Observable = require('observ');
        var svg = require('virtual-dom/virtual-hyperscript/svg');
    
        module.exports = state;
        module.exports = render;
    
        function state(initialPosition) {
            return new Observable(initialPosition || [0,0]);
        }
    
        function render(positionState) {
            var center = positionState();
            return svg('circle', {
                'fill': 'rgba(255, 0, 0, 0.1)',
                'stroke': 'black',
                'stroke-width': '2',
                'cx': center[0],
                'cy': center[1],
                'r': 10
            });
        }
    

The parent component would export its state in the same way. Its own state
would be composed by calling the state() function of its own subcomponents.
Turtles all the way down.

At the top of the app, the saved state would be injected into the state of the
top level component, which would decompose it into parts and inject it into
the state functions of its subcomponents such as the one above.

This single composed state object tree makes it trivial to record diffs in
state for playback or to serialize and save the state to localStorage or the
network.

It's trivial to work with the approach above. As trivial as the local state
approach of react. It's extremely consistent about where state lives. It
doesn't sometimes live in a global place and sometimes live in some other
place. Another developer joining the project doesn't have to hunt around for
where state for a particular value is being maintained. It also makes it
simple to do far more complex things with animation, like build a complex
animation editing application where an animation might be controlled by knobs,
buttons, sliders, dials, etc. With local state you'd have to wire up those
controls directly to the internal state of a component, completely messing up
separation of concerns. With the composed state object, you just write one
function that maps the state of two sliders (x&y) to the state of the circle
and have it listen to change events on the slider position. It's trivial to
wire things up in both directions by having them listen to each other.

Time travel (undo/redo) is also trivial to implement:
[https://github.com/Raynos/mercury/blob/master/time-
travel.js](https://github.com/Raynos/mercury/blob/master/time-travel.js) 67
LOC with generous whitespace.

You could wire up the time-travel state to a slider as well to accomplish
something like this:
[https://www.youtube.com/watch?v=ri614C_Buwg](https://www.youtube.com/watch?v=ri614C_Buwg)

For the viewing state over time features in the froggato level editor you
simply take the series of state over time, use it to instantiate state()
multiple times and render them all in the same frame.

Show one circle:

    
    
        scene -> circleRender(circleStateAtTimePosition(now));
    

Show one circle over time:

    
    
        scene -> circleRender(circleStateAtTimePosition(now - 2));
              -> circleRender(circleStateAtTimePosition(now - 1));
              -> circleRender(circleStateAtTimePosition(now));
              -> circleRender(circleStateAtTimePosition(now + 1));
              -> circleRender(circleStateAtTimePosition(now + 2));
    

Local state simply makes everything much harder to reason about as you move
beyond all but the most trivial apps.

Lastly, for long running ephemeral state animations, you gain the ability to
"cancel" the animation. Imagine you have a "card" animating out from the right
to show a panel, but you click on something else that would close that panel
and open another one. It's much simpler to cancel that animation midway, close
the first card and animate out the second card. The alternative is to add a
bunch of methods to the card class to handle the cancellation logic. If you
need that cancellation logic in other components you need a mixin, but it's
all brittle because its tied to the key names on this.props as opposed to
being able to make a animation controlling function used in an animation
coordinator that merely needs to receive cursors (i.e. nothing is hard coded
to key names)

You might say "but I have no reason to track ephemeral state in that way" and
you would be correct, you don't need to. But there are no disadvantages of
doing so relative to local state. Furthermore you gain predictability about
where state lives and the ability to not worry about refactoring if one day
decide that you want to now control a particular piece of ephemeral state.

------
amirouche
I'm upvoting this because I find reactjs a good development tool and would
like to see more of those articles. That said, the article only explain a
simple case that is not a real world scenario. Others have commented on this
issue in the comments.

------
adeptima
This is out-dated from my perspective. Check Redux
[https://www.youtube.com/watch?v=xsSnOQynTHs](https://www.youtube.com/watch?v=xsSnOQynTHs)
[https://github.com/gaearon/redux/tree/rewrite-docs-
again](https://github.com/gaearon/redux/tree/rewrite-docs-again)

Many Flux implementation lucks of isomorphic, proper hot-reloading, etc. ES6
transition is on its way. Most code will be abandoned. Alt, Reflux, etc are
all in trouble.

------
ihenvyr
Yes please facebook team, update the Todo tutorial.

------
larcara
Great! thanks

------
aikah
React is a good view layer, but React doesn't help me architecture a web
application. React creates an impedance mismatch between how it is supposed to
work(unidirectional data-flow + immutable collections) and how javascript
actually works(everything's mutable). If Flux actually solved something the
right way, we wouldn't need 10 different implementations
(reflux,redux,alt,......). React is extremely smart but clearly not a lot of
thoughts has been put into that flux thing.

