Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Facebook Flux – Application Architecture for Building User Interfaces (github.com/facebook)
255 points by diggan on July 28, 2014 | hide | past | favorite | 57 comments


It's great to see Facebook releasing code for Flux. Hope to see more in the future. Here are some other implementations of Flux for anyone who's interested: https://github.com/BinaryMuse/fluxxor https://github.com/jmreidy/fluxy https://github.com/yahoo/flux-example

We recently adopted this architecture for a medium-scale project. The unidirectional data flow has greatly reduced code complexity for us. We're still not satisfied with our server syncing strategy. Seems like actions are the best place to sync data, but how do you deal with interdependent actions?


I'm the author of Fluxy and would be happy to answer any questions here. The big benefits of Fluxy vs other Flux approaches is that 1) Stores are built on top of immutable data structures (via ClojureScript / mori) 2) Server side rendering is baked in (or will be as of 0.4)

I'd also mention https://github.com/spoike/reflux as an implementation.


Thanks for mentioning my project, Reflux.

I initially thought that the suggested implementation by Facebook was a bit weird because it requires a lot of boiler plate code.

For the longest time I disliked using magic strings for type checking since it breaks the concept of polymorphism. In Javascript it is even more weird considering it is a dynamic language. So I fixed that by moving the type specifics (which in Flux's case is mostly about handling events) into the actions and stores themselves.

Thanks to a contributor we also provide a mixin for React components that adds automatic unsubscription on componentWillUnmount and provides a listenTo method in the components to subscribe to actions and stores.

It works both server-side (available at npm) and client-side (available as bower package or can be built in browserify from npm package).


Thanks for posting - I'm glad to learn about reflux here. I started adding flux to an application as prescribed and thought there were many strange and unnecessary steps. All the flux libraries seemed equally complicated. Instead I went with a simple event emitter approach, which is basically Reflux without the nice API. I will certainly give it a try.


I've been reading about ClojureScript/OM and mori. What example apps are online using either of them? This is what I've found so far.

ClojureScrpt/OM:

https://github.com/swannodette/om (several examples linked)

http://rigsomelight.com/2014/05/01/interactive-programming-f... (flappy bird clone)

React+Mori:

???


Fluxy has an example of using React + Mori - although it's still a work in progress as Fluxy is developed.

https://github.com/jmreidy/fluxy/tree/master/examples/todomv...



We've been exploring Flux pretty heavily here at Yahoo and the idea of utilizing React + Flux stores on the server-side as well. The Yahoo flux-example you linked to is using our own dispatcher (https://github.com/yahoo/dispatchr) that does away with the singleton pattern all of the other Flux documentation and examples have used, making it safe to use on the server.


The React docs talk about this a bit [1]. Have you already tried this? What kind of problems are you encountering?

[1] http://facebook.github.io/react/docs/flux-todo-list.html#add...


Another small attempt using just backbone: https://github.com/shaohua/todomvc-react-flux-backbone


Usually I have an action call out to some DAO class which encapsulates an HTTP request and returns a promise, then just firing off a different action in the done and fail callbacks.


Could you describe what you mean by interdependent actions? As in, chains of actions?


Yes, a chain of actions (for example, a sequence of AJAX requests that need to be fired)


I'm still somewhat unclear on the point of the Dispatcher and Actions and they simply feel like needless indirection to me.

For instance, in the flux-chat app within the linked repo, the MessageComposer component calls `ChatMessageActionCreators.createMessage(text);` when the user press the enter key to submit a message.

To find out how that ends up affecting the application, you need to jump around more than a couple of directories to find out how it's all wired up.

I just cut out the middlemen and directly interfaced my Stores from my components. My Store then emits a change event as usual and other components that are subscribed to the change event than refetch their state. That part of Flux makes perfect sense to me. The need for Dispatchers and Actions don't.

To be fair, I didn't start looking into Flux until my app starting growing large enough that I started feeling the pain of my lack of architecture. The Stores and the event emitter solved my immediate problems. Perhaps if my app grows even larger, the Dispatcher may come in handy.


Came to write the exact same thing. I chatted with some other people on the react irc channel about it and interfacing with stores directly seems to be pretty common. It's been working well for me so far in the smallish app I'm writing now.

To expand a little, I have trouble identifying what the difference between these two flows are;

    (something) -> store method -> change event
    (something) -> "action" -> store method -> change event
Feels like actions on the dispatcher are an unnecessary level of indirection when I have to know that I'm calling a store method under the hood just by virtue of knowing the action to call. I understand batching events and things like that, but manually wiring seems like a really boilerplate heavy solution to the problem.

Now that I'm writing this, I can kind of see the usefulness in making reusable components that can interact with stores. I guess I just felt like reusable components would never interacted with stores (as that's handled by controller-views which are pretty much application specific). But even then they need access to the dispatcher, and if you can inject that dependency then you can inject the store itself...

Sorry for the stream of consciousness, it's my lunch break...


Probably more reasons, but a few off the top of my head: 1) Multiple stores can respond to a single action 2) Single action listener may call multiple store methods 2) Can reduce the number of places a store is modified from


Another benefit is that the Dispatcher handles all the ordering of updates for you. If you have complex relationships between your stores or even if they just must handle updates in a certain order, by sending all updates through the dispatcher you can also force a partial ordering of store updates through dispatcher.waitFor(<other store>)


You can imagine that a key command, a click on a button, or even a command originated from a remote control that arrives proxied over a WebSocket - all of these could create the same Action. Each Store shouldn't care, or have any interest in, what component created that Action. And you should be able to add new Stores and new interaction types at runtime, as if (in music production) you were plugging in a plug-and-play MIDI keyboard and simultaneously adding a new audio plugin that reacts to any MIDI input. The Dispatcher removes any dependencies between these components; everything just needs to know about the Dispatcher.


Just trying to understand here:

What's the practical difference between the dependency on knowing the right action to call to the dispatcher vs. the dependency on calling the Singleton Store method?


I haven't used flux yet, but I'm assuming a single action might call on multiple stores? Eliminates having to handle that in a dependency


But even that action will have to manage the dependencies on these multiple stores, doesn't it? Whether it's called an Action or associated with a Store, does it make a practical difference?


You are absolutely right that actions are just another level of abstraction that come with their own pain, and if the pain they bring does not relieve an even greater pain of not having them then there is no reason to introduce them yet.

In our app, we started feeling the growing pain of a laissez faire approach to internal comms. For us, a user interaction can generate multiple logical state changes in the app, and several related interactions can cause similar/identical changes to take place. So for us, "User Interaction->App Change" is a many-to-many relationship, and Actions help us to wire them together really well. Couple examples -

1. Opening a modal with the detail view of the item. This can happen in several ways (a user click, onload, keyboard shortcut, app event), and it involves multiple steps (ui cleanup, fetching of more info, etc). Having an actions allow us to guarantee that when we want X to happen in the app, all necessary steps will be taken regardless of what causes X or in how many places.

2. Capturing analytics. We log all key interactions for internal analysis, and some events simply do not belong in the store/ViewController/component, so we capture in within the relevant Action. Low-level events are captured within components (e.g. did they press the 'save' button or hit enter), while others are app-level actions (e.g. 'view details') and are captured within Actions. Bonus - as per the point #1 for us multiple user interactions can cause similar app changes, but by also capturing the event within Actions we can easily track all triggers - e.g. was the 'view details' caused by a clicking on a link, using a shortcut, or another app-level change.

3. Refactoring. Most of the app UI is aware of only two things - Actions and (to a lesser extent) getState() of relevant stores. This means that as long as we keep the public interfaces of those two unchanged, we can refactor or even change the implementation as much as we need. Just last week we swapped the inhouse filtering/sorting implementation a for new one based on Crossfilter which caused a comprehensive rejigging of the stores' behaviours and methods, and because we kept the same public contract it had zero impact on the UI (besides a noticeable speed improvement).

Pardon the flawed comparison, but for us actions are useful in a similar way that interfaces or MVC controllers are useful - as long as you keep them lightweight and semantic, they provide predictable and reliable endpoints for the app regardless of what turmoil happens behind the scenes.


I'd be very interested in seeing some Crossfilter-based filtering store code. I've been working on a business application that needs to do quite a bit of filtering and hierarchical rollups, and I'd really like to start using Crossfilter for it so we can chuck the much more limited tool I whipped up when we started the project and get that speed boost you mention.

We're also starting to see a lot of the many-to-many relationships in actions you mentioned, which convinces me we need to work towards more of a Flux architecture (it wasn't out yet when we started this lo those many months ago).


I'd be happy to have a chat over Skype and share what we've done - just drop me a line to [redacted]


Because I didn't want to add so many layers at once, I just implemented Stores -> ControllerView -> View -> direct Store call.

As far as my understanding goes that should be fine for most use-cases. The only reason that really requires a Dispatcher would be synchronization of the incoming Store mutations.


I previously spent time reading about Flux, watching the videos, looking at Flux libs like Fluxxor and it seems overly and unnecessarily complicated to me. The actions layer specifically seems unnecessary as it could be implemented at the Store / model layer. The dispatcher is an event queue system with support for dependencies.

To me it makes a lot more sense for React components to push an event directly onto a pubsub event queue which then dispatches accordingly. When data changes anywhere it fires an event that then passes new state to the top level React component. Most of the actions you do to data are boilerplate and can be greatly simplified from Flux.

What am I missing? Why is it so complex?


Seems like actions were designed to encapsulate update logic that doesn't belong in the store (e.g. update ordering when multiple stores are involved). A pubsub event queue wouldn't make this very easy.


The Dispatcher is not an event queue system, but rather a registry of callbacks. This is a significant difference. The callbacks may be invoked in a specific order, synchronously, so that dependencies between Stores are managed effectively. Stores declare their own dependencies -- the Dispatcher knows nothing of the internals of Stores -- through the use of the dispatcher's waitFor() method.

Yes, you don't absolutely need the ActionCreator helper methods. You could call AppDispatcher.handleViewAction() or even AppDispatcher.dispatch() directly in the View. But keeping these things separated out keeps the code nicely organized and keeps application logic out of the View. Additionally, I find it helps to maintain a mental model where the only way into the data flow is through the creation of an action, codified in the library of ActionCreators.


It has a fine explanation of the pattern: http://facebook.github.io/react/docs/flux-overview.html but what isthe reasoning in using this architecture? Or in pattern speak, what are the forces that this pattern is considering? I can't find a clear explanation about which problems is it trying to solve.


In larger web based applications, tracking down side effects becomes increasingly difficult with patterns that implement two-way data binding (observables) or ad-hoc injection. This also in part takes into account part of why React renders the way it does. With the flux pattern(s) along with React's rendering pipelines, you can have heavy data flows, with minimal side effects and a slightly easier time in terms of tracing the flow of data.


Encouraging composition and simplifying event flow.


We've got a React Flux series[1] on egghead.io if you like video lessons.

--

[1] https://egghead.io/series/react-flux-architecture


I've been using React quite a bit but haven't had a need for Flux. Using React to implement all of my UI concerns, combined with Backbone for easy to use persistence and modeling, has worked wonderfully for me. YMMV :)


I agree. The combination of Backbone models/collections and React views bound together by React.Backbone[1] so that the views automatically re-render after any changes to the models/collections has made the data-heavy application I'm working on surprisingly easy to develop.

The real issue I've been having React -- that I'd I like to see dealt with by a library/design pattern -- is dealing with transitions between view states. Re-rendering the view on any data change can result in very abrupt changes. For instance, my app displays multiple lists of items. When the user edits an item, that can result in the item suddenly disappearing from underneath their cursor to reappear somewhere else in that list, in a different list, or nowhere within view.

I've been able to handle each issue of this nature as it arises in an ad-hoc fashion, but I'd really like a more formalized way in React to say, "when attribute X changes, use transition Y to change from the old view state to the new one".

Does anyone know of an existing solution to this problem?

[1] https://github.com/usepropeller/react.backbone


Check this out: https://github.com/andreypopp/react-router-page-transition

Not simply react but you can get the idea.


I think this is the best combination of libraries I've ever used, but given how impressive React truly is, I'm sure I'll see the Flux light soon enough too.


A lot of this seems like it's just MVC, except what they call the "View" is a traditional MVC Controller (the UI element that handles user interactions and sends these to the Model), what they call the "Controller-View" is a traditional MVC View (something that gets notified when the Model changes and displays that change to the user), and what they call the Dispatcher is what traditional MVC calls the Model.

They write "Flux eschews MVC in favor of a unidirectional data flow", but MVC already has a unidirectional data flow (Controller -> Model -> View). Is this just a case of those who don't understand MVC are compelled to reinvent it?

EDIT: Actually, the main addition over MVC seems to be that the Stores declaratively specify their relationships between one another (which are then resolved by the dispatcher), rather than the developer writing a specific Model implementation that explicitly orders the changes to related elements of the model. I'm a bit suspicious that this would be less explicit, and so harder to maintain, but maybe I'm wrong.


The main difference between Flux and MVC is the unidirectional data flow. In MVC, a controller updates a model which updates a view which again talks directly to a model that might invoke another view which again might cause a model update, and so on. In Flux, the only thing a view can do is to invoke actions on the top-level dispatcher. Furthermore, views are never partially updated, they are always re-rendered from scratch every time (like you typically do in the back-end).


But as I said, MVC already has unidirectional data flow. An MVC View doesn't make changes to the Model, so can't lead to cascading updates of other Views.


Actual site for the project:

http://facebook.github.io/flux/

Seems to still be in flux.


It's easy to integrate with Backbone if you want for this kind of architecture, as it already implements events and stores. I've found it requires less boilerplate than the example in the repo.


I just wrapped up the initial version of a medium-size app using React. It was my first use of the library in production.

I had originally used Backbone.Model and Backbone.Collection in conjunction with React. But after reading about Flux on the React blog and watching the video explanation back in May, it only took me a week to replace all of my Backbone models and collections with Flux singleton-stores. Coupled with Andrey Popp's react-router-component[0] (now replaced by rrouter[1], I think?), I was able to remove Backbone from the project entirely.

I think that Flux is more flexible than Backbone. I really like the ability for a store to take on characteristics of both models and collections. It is also easy to combine many different external resources to compose the "one true source" of a particular type of data for many different components. I don't feel any particular need to bring back a Backbone dependency in future React projects.

[0] https://github.com/andreypopp/react-router-component

[1] https://github.com/andreypopp/rrouter


First it was react-app-controller which was deprecated in favor of react-router-component which is now being deprecated in favor of rrouter.

At least Andrey add his reasoning for the latest deprecation in rrouter's documentation. Although the page regarding server-side regarding in the rrouter docs is empty :(

According to the docs "RRouter was developed to replace react-router-component and fix design flaws introduced by it." Maybe I'm just unfamiliar with the npm community but is it typical to just rename projects once they introduce breaking changes?


We've been playing with this architecture. It makes testing a lot easier - you just shove data in where needed and things pop out the other end. It also forces us into splitting things up in a more sensible manner. Along with easier testing is easier reasoning.

That said, like most new architectures/frameworks finding a big example (not just a TODO app) is really hard. We are currently prototyping a big app using React/Flux and we find ourselves having to question ourselves a lot more than we'd like.


Is there any chance your code is public?


FB seems to be doing some amazing work trying to make the web a more tolerable UI platform.

Once we finally have a good, solid, stable UI building consensus in HTML5/JS, it'll not only be possible to use it for the web but for the desktop too via node-webkit / atom-core.


How does this compare with FRP?

I've been thinking about this and concluding that React wouldn't benefit even a little from those FRP libraries and architecture, it is already quite functional reactive. Am I wrong?


React is not functional reactive by itself. Although there's no stopping people from integrating it with other FRP libraries.


Well, I know that.


This looks very interesting, and if I'm not mistaken, slightly reminiscent of how apps are built with Om (using core.async for dispatch and atoms for storage).


Excellent! Been waiting to see an "official" implementation of this. There's a lot of different information floating around about how Flux architecture "should be done", but I've been waiting anxiously to see how Facebook actually implements it/suggests it be implemented.


So, does this make stores 'Flux capacitors'? (pretty pls)


Already tried, but they wouldn't go for it :) https://github.com/facebook/react/issues/1811


I know is stylized as "f.lux" but fuck man...

Why does big companies do that? Just recently Apple's Swift and now Facebook's Flux.


Flux (stylized "f.lux") refers to the awesome screen dimming/coloring software: https://justgetflux.com/ Completely unrelated, but I highly recommend it for anyone who stares at a screen for a living.


What are you talking about? Facebook is calling it "Flux" not "f.lux".





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: