Classical and Functional React Get Married and Bind the Knot in a Decorated Wedding

Gil Birman
3 min readJun 30, 2015

--

Two weeks ago, I described how to setup a simple, powerful, and highly performant functional architecture using immutable data structures in React with less than 100 lines of code. To summarize, by utilizing immutable data structures and a two-line subedit function, we were able to construct some simple mixins that automatically optimized shouldComponentUpdate to have a runtime of O(1) for arbitrarily large data sets.

Now, we’ll again use those lessons learned but instead of instantiating components with our bespoke component function, we’ll use idiomatic ES2015 (ES6) classes that extend React’s built-in Component class, with a sprinkling of ES2016 (ES7) decorators to take the place of mixins.

If all that ES2016 stuff sounds highly experimental and futuristic, well, that’s because it is. But the future is fun and exciting and we can live in it now thanks to the amazing babel compiler (configured to activate stage 0). In the previous article and in this one, I’ll assume basic understand of ES2015. However, since some of these ES2016 features are so new I’ll give a brief intro to the three ES2016 features that we’ll need.

ES2016, it’s easy-peasy

Static Class Properties

class Foo {
static baz = "Doitashimashite!" // ES2016
}

… is the same as:

class Foo {}                     // ES2015
Foo.baz = "Doitashimashite!";

Function Bind Operator

var f = ::this.foo;          // ES2016

… is the same as:

var f = this.foo.bind(this); // ES5

Decorators

@fooDecorator                        // ES2016
class Bar {}

… is the same as:

const Bar = fooDecorator(class {});  // ES2015

… note that a decorator is just an elegant way to wrap a class in a function. Also, fooDecorator is just a normal function, but the @ allows us to apply it in this new way.

Note: the above is unfortunately an over-simplification of ES7 decorators, but it’s a decent mental-model for our purposes.

Decorating our Classical Components

So let’s cut right to the chase. Last time, I demonstrated the style that’s popular with FP advocates where a component is just a render function. It looked like this:

As you may recall, the component function is doing more than just calling React.createClass. It’s also applying two mixins that super-charge our React components. So, how does this translate into classical, idiomatic React? Easy! with a simple decorator that we’ll call elegant:

Now isn’t that simple and beautiful and — dare I say — elegant? But what the heck is going on here? Let’s take a look under the hood.

As a reminder, here is what our original component function looked like:

Pretty darn simple, huh? Well our elegant decorator is just as simple, though somewhat different in it’s effect:

When we place our @elegant decorator before the Hello component, it passes the class expression into our elegant function and assigns the result to Hello. In other words, it’s doing this:

const Hello = elegant(class Hello { /*...*/ });

The resulting value of Hello is a component which wraps our component. This is the higher-order component pattern.

Notice that we are using the same mixins here as we did in the component function (component-render-mixin and statics-mixin), however we are not using them as mixins. Instead, we are creating a higher-order component and wrapping it around the DecoratedComponent.

Also note the use of ES2016 static class properties displayName and DecoratedComponent.

Demo: Phone Number Input

In the previous article I presented this same exact demo using the component function. I won’t repost it here, but check it out if you haven’t already because there is some additional explanation there about how it works.

Take note of the ES2016 function bind syntax on line 61. This is necessary because React components instantiated by extending Component don’t auto-bind the way that React components created with React.createClass do. Of course, you could use ES5 binding syntax instead but that’s old hat :P

On Github

(Updated 7/3/2015) Since I wrote this article elegant-react has continued to evolve. The version that this article refers to is still available, and forever frozen on github in the elegant-react-og repo. The newer version is available in the elegant-react repo. The concepts described in this article still apply to the latest version, however many improvements and changes have been made. The biggest change is that static props are now just regular props which are made static by passing arguments into the elegant decorator.

More In the Works

Two weeks ago I mentioned that I’ve been exploring reactive streams as an alternative to using Flux. If you’d like to get a sneak-peak, check out this demo in the elegant-react repo.

--

--