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.
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.
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.
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.
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.
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.
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!
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).
The "waitFor" implementation makes the stores ordered and circular dependencies impossible, so the data flow is actually unidirectional. It's just that some stores are "before" other stores, even if I didn't show this in the diagram. Maybe I should update it putting the "destination" store for the horizontal line a bit below the other two - so the line wouldn't be horizontal anymore.
Yes but how do we manage inter-store notifications? bubbling up to the root store and down to the other store? Do we post messages/actions for that , or do we call referenced stores directly?
It seems flux just pushed the binding thing up a level, but the complexity is still there.
I use BaconJS as a FRP library to deal with async and store communication. In that way, you will have the root store that combines all events from child store. Then the root tree component will listen for these events to render.
With this architecture, you need to separate the root stores correctly based on those events, which needs to be independent from each other root stores.
One benefit of this approach is that, you don't need to deal with Dispatcher, ActionCreator, Constant, blablahh.
You just need actions(optional) and stores.
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.
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.
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.
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.
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.
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).
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?
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.
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).
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.
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.
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));
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.
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.
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.
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.
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.