The Case for a Stricter Flux

addthis-react-flux-javascript-scaling

With companies like Yahoo, AirBnB, Atlassian, and Github embracing React.js, I think it’s safe to say that Facebook has set a new standard in front-end development with this remarkable library. What drew me to React, at first, was its genius approach to rendering. What has kept me using it are things like propTypes, invariant, and the belief that it’s a library’s responsibility to yell at a developer when they are doing something wrong.

While React does provide a really swell way to render views, it intentionally does not provide a framework for control and management of data. Enter Flux: a simple paradigm that creates easy-to follow, easy-to-debug flow of information through your application.

It’s important to know that Flux is not a framework. Flux is more of a design pattern than a piece of code. Flux only works when developers hold themselves to certain conventions, which are sometimes not so obvious. When a developer makes the inevitable mistake, we only sometimes see the error propagate its way into an invariant thrown by React or the Flux dispatcher. The rest of the time, these mistakes manifest themselves in strange and unpredictable ways.

Consider the following code from Facebook’s own page on using Flux:


var _todos = {};
/*...*/
var TodoStore = merge(EventEmitter.prototype, {

  /**
   * Get the entire collection of TODOs.
   * @return {object}
   */
  getAll: function() {
    return _todos;
  },

  /*...*/
}

It might not be obvious how dangerous the code above is. Clearly, an attempt to make _todos private to the store has been made by the developer, yet the store exposes the object through a public function. All a view needs to do to completely break the Flux cycle is delete TodoStore.getAll().id. You’ve probably run in to this if you’re developing an application with Flux and not using an Immutable library—and you probably also know it’s now time to bring out the defensive cloning:


var TodoStore = merge(EventEmitter.prototype, {
  /*...*/
  getAll: function() {
    return $.extend(true, {}, _todos);
  },
  /*...*/
}

But that doesn’t solve every problem. Imagine your view receives the result of a call to getAll as a prop, and then passes this prop along to the various children that need it:


<Todo data={this.props.todos[0]}>
    <TodoLabel id=this.props.todos[0].id>
        {this.props.todos[0].description}
    </TodoLabel>
</Todo>

What happens when a developer makes the mistake of mutating one of their props? It’s certainly convention to not do this, but it’s easy enough to flub.


var todo = this.props.todo;
/*...*/
function saveTodo(todo) {
    todo.id = generateUUID();
    //description -> text for legacy support
    todo.text = todo.description;
    delete todo.description;
}

Clearly we are going to have some problems, now that this mutable, cloned copy is being shared by multiple components. This kind of thing is a nightmare to debug. Why wasn’t it stopped earlier? Why do our stores even allow us to use anything other than immutable data?

At AddThis, we’re using the hand-made Flux components provided by Facebook, but all the devs here have felt the pains I’ve enumerated above. These are the kinds of pains a framework should solve. There are a few Flux frameworks in the wild right now, but they all seem focused on reducing boilerplate (a noble goal, but should it be the only one?). Until a Flux framework can give us the rigidity that React does for views, we won’t invest the time to migrate to one.

  • Jake

    I’m working to move our stores over to use immutable-js :)
    Still though, it would be nice if there was no way to store mutable data in the first place, so mistakes could have been completely avoided.

  • Jake

    I haven’t heard of this one before, but I will definitely check it out. Thanks!

  • Barbora Galandakova

    Hi there,

    great article. We are looking for a reactjs and flux or nod genius :)
    Bit exaggerated, but it seems really hard to find a developer who is good and still wanting to learn new things.

    Our “thing” is called Shoutit. Online market place covering anything, anyone might like to sell, exchange, gift or buy, featuring fully functioning instant messenger.
    Apps are functioning well. We got 100K users in 3 months after launching. So it seems to make sense :) Now what we need is a hero to bring our webapp to the next level.

    If you are one or know of someone, send us an email at: info@shoutit.com

    Cheers
    Barbora

  • Barbora Galandakova

    Hi there,

    great article. We are looking for a reactjs and flux or nod genius :)
    Bit exaggerated, but it seems really hard to find a developer who is good and still wanting to learn new things.

    Our “thing” is called Shoutit. Online market place covering anything, anyone might like to sell, exchange, gift or buy, featuring fully functioning instant messenger.
    Apps are functioning well. We got 100K users in 3 months after launching. So it seems to make sense :) Now what we need is a hero to bring our webapp to the next level.

    If you are one or know of someone, send us an email at: info@shoutit.com

    Cheers
    Barbora