Flux isn’t solved

Blaine Kasten
In The Hudl
5 min readJun 1, 2016

--

Why does innovation stop when good solutions come out? There can always be something better. That goes for every language, framework, computer system, life skill, etc. In some ways this post is a post of frustration to this idea. Innovation should never stop, anywhere. We’ll always have more to figure out. And we can always come up with better ways to do existing things.

Just imagine if ember, and angular, and all other view library's were deprecated when React came out. At that point, 6 developers would be in charge of how views are handled on the web, worldwide; 6 people with limited scope to what the world needs for each individual solution. That is the exact pattern the web has beautifully avoided, by having committees and working groups (e.g, TC39, W3C). People who have different challenges to face, and different levels of scalabilty to solve. The web is great because everyone has new and unique ideas. And each idea contributes to its betterment.

If you've tracked along with the history of flux, this has generally been true. Facebook announced Flux at F8 in 2014. Excitement and confusion ensued. The pattern seemed brilliant, but there wasn’t any clear direction that helped a user construct this pattern. Within months there was an explosion of innovation. Some libraries, like Ken Wheeler's McFly or Mikael Brassman's Reflux, that simply added structure to this pattern. Or newer ideas like Dan Abromov's redux or Michel Weststrate's Mobx actually changed a few things along the way. Each, building off of the previous, innovating on existing ideas to make them better. Innovating on the original idea of Flux, to make it better for the ecosystem.

If you're reading this, you likely know redux. Famously, redux did this best (so far). Dan Abramov took the ideas of flux, but in a whole new spin. Reducers, composers, single store. All smart ideas to reduce complexity and increase predictability in your flux patterns. It really is a beautiful library that everyone should at least look into.

But here is where my frustration comes in. Redux blew onto the scene and became the sole focus of react developers when looking for a flux solution. In general, innovation stopped (note: Mobx is gaining traction!). To be clear, this isn’t a post to say “stop using redux.” For the most part, I really like redux. But I don't think it's perfect. So this blog is more a post to say, “keep creating tools and using what makes sense for your project.” So that's what I've done.

Just to be clear, all this is said in an effort to get buy-in with this flux library I’ve been working on. But it builds on the principles I'm stating. Meaning, I don't think this library is *the* solution for flux. I see it as a small evolution of what exists already, and hopefully it can be evolved further. With all that said, I want to introduce to you coflux.

coflux

coflux was built to be simple to architect and easy to reason about with as little boiler-plate as possible.

It is often easier to architect coflux compared to other implementations as it doesn’t require the developer to figure out where to put actions, reducers, constants, etc. In coflux that all lives with your components. When flux lives with your component you get an added benefit: you can place your component anywhere in a tree and it should just work.

High-level

To give you a high level, this is simple statements to describe coflux:

* Single store
* Actions are reducers
* Actions are inline with your components
* ACTION_TYPE is gone.
* Components are automatically re-rendered in the smallest flow possible
* Manually passing props are purely for UI. State is automatically connected.

As noted, the main difference you’ll see in coflux and other flux implementations is that your flux actions/handlers are inline with each component, and only accessible by that component. This might turn people off, but it’s a very intentional design decision. My experience with working on large-scale SPA react+flux applications, it gets difficult tracking down which reducer is modifying state based on an ACTION_TYPE. It’s additionally difficult to know what ACTION_TYPE’s are available throughout your entire application, and know their argument requirements. By having these actions inline with your component, you can see at a glance what your component looks like, what it can do, what state it is aware of, and how it can modify that state. Here is what a simple component might look like:

/*
* let’s assume a Higher-Order State tree like this:
* const state = {
* user: {
* name: 'Blaine Kasten',
* id: '128941712',
* email: 'blainekasten@gmail.com',
* },
* };
*/

function CustomInput({actions, name}) {
return (
<input onChange={actions.updateName} value={name} />
);
}
import { wrap } from 'coflux';export default wrap(CustomInput, {
mapStateToProps() {
return {
name: 'user.name', // path selector to state slice
};
},
actions: {
updateName(state, next, e) {
// updates ‘user.name’ state slice with e.value;
next({name: e.value});
},
},
});

With this implementation, your component is incredibly light. It is given the slice of state as props, and an actions object on props that is all of your defined actions. All of it is scoped to the slice of state you map to your component. You’ll notice that ACTION_TYPE is not involved here. When designing, that was seen as a part of the multi-store flux design. With a single-store design where you only have 1 reducer for an action, the abstract ACTION_TYPE had no place. Instead we just get direct access to functions.

The only other part of the API is your Provider. This is extremely similar to react-redux’s Provider API. You provide it a default store, and that’s what you are working upon. Here is how a general application looks:


import { Provider } from 'coflux';
const store = {
user: {
name: 'Blaine Kasten',
id: '128941712',
email: 'blainekasten@gmail.com',
},
todos: loadTodosSync(),
};
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, domNode
);

The API is extremely simple. It’s built to be simple to understand what your components are doing. To wrap up, this is just an attempt to innovate on the smart minds of flux’rs before me. I’m not sure if this is really the next level or not. But it’s an attempt. I hope at the very least, somebody is inspired by this library to design and build what really is the next level for flux libraries. I am very looking forward to community feedback on this library. Let me know if you think it is next level, or back a step. Keep innovating, don’t settle. Know your tools, and use what is right for your project.

If you are interested in coflux, please check it out on github https://github.com/blainekasten/coflux. Contribute to it. Help make it better.

Thanks

A big thanks to the shoulders of giants I stand upon. This is all truly a community effort, and flux would not be what it is without involving so many great minds. All the people I listed above with their flux contributions and those I didn’t know to include. Thank you. Thanks to Dustan Kasten for reviewing this article.

--

--