10 ms·
Flux Application Architecture
- clarkevans 12y agoThe 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 12y agoAgreed, we found that property really nice too - optimistic updating and rolling back on error were similarly easy
- deleted 12y ago[deleted]
- frik 12y agoI 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?
- jacquesm 12y agoIt looks like continuations in a slightly different guise to me. http://en.wikipedia.org/wiki/Continuation#In_Web_development http://en.wikipedia.org/wiki/Continuation#In_Web_development
- porker 12y agoIs your framework available anywhere? I'd be curious to take a look.
- frik 12y agoI will write a blog post about it in the next days.
- mattgreenrocks 12y agoThe Dispatcher part reminded me of the Proactor pattern from days of yore. This is a different domain, of course.
- sarhus 12y agoSomeone in the video asked a question about how AngularJS compares against Flux+React. Anyone has a more detailed explanation?
- sehr 12y agoI've found a couple of links regarding React without Flux vs Angular: http://www.quora.com/Pete-Hunt/Posts/Facebooks-React-vs-AngularJS-A-Closer-Look http://www.quora.com/Pete-Hunt/Posts/Facebooks-React-vs-Angu... http://www.reddit.com/r/javascript/comments/1oo1y8 http://www.reddit.com/r/javascript/comments/1oo1y8 Though they're both from a member of the React team and might be a little biased, they were very informative.
- grayrest 12y agoFor 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-correct http://www.confreaks.com/videos/3221-mwjs-be-predictable-not... Flux is just Facebook's internal usage pattern. Doesn't really have an Angular equivalent other than the somewhat nebulous Angular best practices.
- pacala 12y agoReally 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.
- couchand 12y agoI've been doing a fair amount of Angular development at work and recently been getting into React on the side (and now introducing it for a new project at work!). I'd say they have the same general goal - build your app with declarative and expressive markup. However, Angular tries to shoehorn custom components into the regular DOM, which gets problematic in many cases. For instance: the directives `ng-show` and `ng-hide` simply apply CSS styles. As far as I know it's not possible to completely remove an Angular component from the DOM and then replace it later (without getting too deep into imperative JS). However, that's trivial to do in React. Angular chokes on large data sets, probably because it's doing everything directly on the DOM. React handles huge numbers of records effortlessly. Getting comparable performance with Angular requires much more imperative voodoo than I'd like out of an ostensibly declarative system. I also find it harder to reason about Angular's data flow, since there are many ways to pass things around: nested scope, isolate scope, sibling scope, same scope, dependency injection to name a few. Finding where a particular handler or value comes from is sometimes quite the hunt. With React, it's all pretty much self-contained.
- swah 12y agoCan 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 12y agoThis architecture describes how data affects presentation and vice versa. Your question is a bit off, it involves implementation, not structure.
- swah 12y agoOk, I also don't quite understand if the Store has any relation to the server-side database.
- colinramsay 12y agoIt'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.
- jingc 12y agoYup, we've used it that way, and it's easy to implement due to the fact that all changes are expressed as a payload object, which allows you to serialize actions. Optimistic actions (showing the Like when the server hasn't confirmed yet) are built the same way - the stores just need to resolve between the optimistic/offline update and the eventual server response.
- vdm 12y agoI think you could do this in a Store component which uses a ServiceWorker.
- lhorie 12y agoI 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 12y agoThanks 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 12y agoThat 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.
- OliverM 12y agoI 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 12y agoI 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.
- OliverM 12y agoI 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...
- rattray 12y agoVideo 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.
- jamesgpearce 12y agoYeah, we should have embedded it to skip me, for sure :)
- shaohua 12y agoJing did an amazing job explaining Flux. She should do a lot of more of those talks.
- wingspan 12y agoFrom 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.
- couchand 12y agoThanks for the encouragement! I'm using React to build a new project at work and so far I've been very satisfied with how much it gets out of the way. Perhaps promises would be a good solution to your action spaghetti? They can deliver progress, completed, and error messages targeted to the place that cares about them, rather than passing context through the entire rest of the system.
- wingspan 12y ago
- hamxiaoz 12y agoThis looks good. I'm wondering has anyone combined react and meteor in a real project?
- rdtsc 12y agoI 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.
- mmerickel 12y agoIt 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.
- modarts 12y agoSame here: i'm not seeing the value of the additional indirection.
- jingc 12y agoThe 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.
- bkurtz13 12y agoI would like to see a boilerplate example of this architecture, especially the dispatcher.
- dan15 12y agoThere'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.
- blktiger 12y agoSeems 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 12y agoIn 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)
- gbrits 12y agoWatching 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.