Coding with React like a Game Developer

Awesome ES6 patterns for React + Flux

26th of January 2017 Note: This is fairly out of date, and possibly not even worth the read anymore. I unfortunately didn’t continue writing articles like these to document the many shifts in the React best practices. But I hope I’ll be able to write new articles on Reactive Programming + React soon.


ECMAScript 6 is on the rise. If you haven’t heard of it yet — which is very improbable — it’s the next version of JavaScript. And it’s a major overhaul compared to the old ECMAScript 5 standard, that is currently in use by any major JavaScript engine.

Many features are already on their way to be implemented and those features are simply put awesome!

As a JavaScript developer you’re much like a game developer. You’re in a constricted environment, that has its quirks. But with ES6 it feels like we can finally clean up some JavaScript weirdness and even smarter patterns, that fully embraces the new standard.

With Sebastian McKenzie’s Babel you can use ES6 today. Babel is a JavaScript compiler, so you can just throw it into your Grunt / Webpack / Gulp / whatever build system and let it compile awesome ES6 code into plain ES5 code.


What does that mean for your React (+ Flux) project?

Using ES6 you can turbo-charge your React code. Promised —

There are simple, small changes that general JavaScript code really benefits from, like “Arrow functions”, or “let + const”, or the enhanced object literals, or template strings, or…

The list just goes on and on.

But what React code is really benefitting from are the ES6 classes. They are mainly just a new layer above the old prototype-syntax, but they really make working with an OO-structure much easier.

The React team is trying to embrace the ES6 standard, so they put much effort into making React very compliant to it and they try to stick to the new patterns as closely as possible.


In the last weeks I experimented much with ES6 and tried to come up with new React patterns, which are more convenient than those you see in many React sample code snippets. This article is a collection of what I’ve learned and came up with.

Components

They are the heart of each and every app that uses React. You’ll spend most of your time coding in components, I guess.

In January the React team released React version 0.13.0 Beta 1. The minor version jump introduced many nice changes and some additions. One of those additions was: Writing React components as plain ES6 classes.

Let’s take a look at some sample code

This is your boring, old React component. Not much to see here. We’ve got a state value, a very simple render function and an onClick handler.

So how does this look in ES6?

Copyright 2008, Focus Shift
“Oh, wow! Wtf?!” — ES6 Novice

There’s much going on here so let’s break it down.

The first line is ES6's new module importing syntax. Not only does it do simple imports, like:

import MyFood from "my-food";

We can also expand imported objects and select certain keys:

import { Sushi, Spaghetti } from "my-food";

The next line is a bit more complex. There’s the module exporting syntax in there. Basically you’ve got two options.

1.) With the export keyword you export something into as a key into module.exports. It’s the equivalent of doing:

// ES5
module.exports = {
Sushi: Sushi,
Spaghetti: Spaghetti
};
// ES6
export Sushi;
export Spaghetti;

2.) With the export default keyword you export a single object. It is basically assigned to module.exports:

// ES5
module.exports = MyFood;
// ES6
export default MyFood;

Now we’ve finally got the new class syntax. The React component is created by extending your component based on React.Component. A nice OO-based approach done right.

With ES6's class syntax you don’t need object literals anymore. Thus no commata and nothing like function keywords. Just plain functions declarations as you’d expect them:

class HelloWorld extends React.Component {
render() {
// ...
}
}

But suddenly it gets weird: You can’t initialise properties! There is nothing implemented in ES6 to do that. Still the React team wanted to drop the getInitialState method, so the state would be a simple instance property. You’d expect that you could do:

class HelloWorld extends React.Component {
state = { world: "World" };
render() {
// ...
}
}

But Property Initialisation is not implemented in ES6. That’s why it was moved to the constructor:

class HelloWorld extends React.Component {
constructor(props) {
super(props);
this.state = { world: "World" };
}
// ...
}

Sorry, but it gets even worse! What do you do with your static properties, like “propTypes” or “defaultProps”? Well there are static methods, but as there’s no property initialisation, there’s no inline static property syntax.

That’s why there are these lines at the bottom:

// ...
HelloWorld.propTypes = {
food: React.PropTypes.array
};
HelloWorld.defaultProps = {
food: [ "Pizza", "Lasagna", "Sushi" ]
};

“Dude, Where’s My Autobinding?” — Reactor

The function used in the onClick prop on line 20 is not the same as it was with React.createClass:

// This old line...
<h1 onClick={this._onClick}>
// ...turned into
<h1 onClick={this._onClick.bind(this)}>

React had a magic feature called: Autobinding. You could reference functions in the same class without binding it to them. This felt really awesome and prevented repetitive code.

Unfortunately this is not what a plain ES6 class does and the React team decided to remove the feature from React classes.


On line 25 you’ve got another neat feature of ES6: Arrow Functions.

They are small anonymous functions, that don’t create a new scope. They are like an anonymous function literally that was bound to the current scope using “.bind(this)”.

// ES5
{
array.map(function(obj) {
return <li>{obj}</li>;
})
}
// ES6
{
array.map(obj => <li>{obj}</li>)
}

Even when you use the expanded style, it’s still great:

// ES5
var anon = function() {
}.bind(this);
// ES6
let anon = () => {
};

“Dude, Where’s My Mixin?” — Reactor

To quote the blog post that announced React v0.13.0 Beta 1:

Unfortunately, we will not launch any mixin support for ES6 classes in React. That would defeat the purpose of only using idiomatic JavaScript concepts.

No comment. Really.


It’s great, but does it feel “smart”?

Classes are perfect for React. The method for creating components is called createClass after all. They just make React more idiomatic. Still, in my opinion the React team overdid it.

Mixins were great, they enabled you to reuse code easily.

The getInitialState method and the getDefaultProps method were nice. They were maybe not idiomatic for instance properties, but that didn’t matter, because their sense was obvious.

The same for Autobinding: If someone forgets about Autobinding and wonders why his code doesn’t work in other classes, that is because it’s just so nice and convenient.


The old React way + ES6 class pattern

Luckily I’ve got the solution, folks. I wrote a compatibility class, called “CompatComponent”. It extends React.Component, and reintroduces many of React.createClass’s features into the React component classes.

You can find it here: https://github.com/philplckthun/react-compat-component

Let’s look at our example code, using CompatComponent:

As you can see I fixed the problems, that I complained about earlier in this article.

To solve the missing property initialisation feature, I did the exact opposite of what the React team went for. I made propTypes into a function and thus introduced getPropTypes instead of moving the state initialisation into the constructor and turning getDefaultProps into a property as well.

I also reintroduced mixins and autobinding. The mixins are now defined in the getMixins function.

Stores

I always felt that with Flux, the React team introduced a nice dispatcher for a unidirectional data flow, but I think they delivered a lousy pattern for the stores themselves.

This is a modified example store from the TodoMVC app, in the Flux GitHub repository. So this is the pattern, that the React team would like us to use for stores:

First thing, that bothered me here: Why is there an object as the store in there? Let’s put an immutable Map or List there. With Lee Byron’s Immutable.js you get very efficient immutable data structures written in pure JavaScript.

The advantage of immutable objects are, that they obviously don’t change that easily. It’s easy to compare them with a standard comparator:

oldImmutableStore === newImmutableStore

This is great for React components, when they have to decide whether to rerender. You can throw in an ImmutableRenderMixin, which implements the shouldComponentUpdate method to just check the equality of the state and props.

More on how to implement that efficiently later.


How should we make use of this store?

Now according to the examples you should do something like this:

So this component registers a change handler and updates a state attribute if anything changes. The Store itself is an extension of an EventEmitter, and on any change it emits a change event. So obviously the component is always up to date.


So what’s the matter with this?

There’s a promising pattern, that makes this pattern unnecessary bloated. It’s a kind of “higher-order component” pattern. You create an anonymous parent-component wrapper, that injects the store’s data as a prop.

Furthermore you can create a store class that you can extend to create new stores. The store pattern, that the React team delivered is very repetitive. That’s nice, because now we can outsource it into a seperate class, that we can base our specialised stores on.

And lastly we can use Immutable.js to make this even more efficient.

I find this to be a very efficient and clean pattern. Following I’ll show you and break down my Store class, Transmit class and an example.


The Store Factory

Originally I implemented a Store class, that could be extended to generate custom stores, but this class would have to be used as a singleton anyway which makes the Dispatcher modify a single child of a useless class.(https://gist.github.com/philplckthun/ffffd2dd30f51cd97e3c)

To optimise this I wrote factory, that spits out just the child as a simple object. Why this is actually more powerful than using the new ES6 classes is excellently explained in Eric Elliot’s article “The Two Pillars of JavaScript”.

I’m also using RxJS’ observables instead of pure EventEmitters. Observables are nice event streams, that are like a combination of EventEmitters, Promises and iterators. They are a bit like node.js’ streams, but at the same time different.

You’ve got nice promise-like data streams, that can be combined, filtered, or mapped. It’s really powerful and I recommend this particular talk here to learn about it: https://www.youtube.com/watch?v=2btEt0W7UxU

So here’s my Store factory. It’s simplified to keep it short:

This class is very short, but it can already insert new data and output it as a list. We use Immutable’s Map to store elements via their / an ID. In the get method we can output a List instead. This discards the keys and lets us list the items very quickly.

I think it is easy to guess the functionality of each method, but anyway here’s the documentation for Immutable.js.


The Transmit Class

Now how do we create a component quickly, that wraps our original component and inserts the data? We’ve already got the Store, so we’ll create a class that takes a component and a store as arguments in its constructor and creates an anonymous wrapper component.

This is similar to what the Relay or the React-Transmit library do.

It’s a very simple class. It saves the Store’s data into its own state, registers a handler to the change listener and updates the state accordingly. Then it injects the state into an instance of the component, that was passed to it. It also passes on all the props.

I you’re wondering, “object-assign” is a module, that takes multiple objects and merges them into a new object.


Applying those two classes

Let’s say we want to have a store for our food and a component that lists it?

As you can see all the “boilerplate” repetitive code is gone. It resides in the parent classes now.

RESTful API

Coming soon…


I’ll try to keep this article up to date and write new sections from time to time. Follow me on Twitter to keep up: @PhilPlckthun

I’d like to know whether what I think and write made a difference, so please “Recommend” this article to your friends and leave a comment, if you’d love this article to be expanded.