This past weekend I had the pleasure of attending Hack24 which is a hackathon organised in my local area. It was a great opportunity to enjoy being part of my local development community as well as a good opportunity to finally meet in person some people who I’ve been working with online over the course of the past year or so Jamie from A journey in dot net core, James from Cynical Developer podcast and Paul from codeshare.co.uk.

But the best part of the weekend for me was the “OMG what have I learned?!” moment I had at about 3:30am whilst I was reading a blog post about how to put Firebase Auth and React router together for the React front end for our Hack entry.

The blog post itself I found to be a little out of date, however, the code did have one very interesting property. The event handlers….they weren’t having this bound to them in the constructor?! And yet if I copied the code directly then, sure enough, it worked. I didn’t know what this wizardry was, but I liked it and I was excited to learn more….right after a nap.

 

What is this React? Look at me?! What is this…?

As an advocate of React I, almost on a daily basis, have conversations with people at all different stages of their React journey. From people who are just deciding whether they should bother with learning React, right up to people who are on a Yoda level of React grok compared to me.

One thing that often comes up when I talk to people who are newer in the React scene is the different things we do in React that they don’t like. Sure, there are times I get to talk about the good things too but generally when people are getting in touch to agree with you that React is awesome it ends up being a much shorter conversation than when I have to go into bat to defend React’s quirks.

One of the quirks that I often find myself defending is not even really a React quirk at all but rather a javascript quirk. None the less the problem is surfaced in the flow of working with React so people tend to assume that it is a React thing.

That quirk is the fact that in order for event handlers in a React component to work correctly you often find that you need to add a call to reinitialise your event handlers and bind this to the instance of the component itself.

Adding these calls to bind this to the functions isn’t inherently a problem but the reservations people most often have with it is not necessarily the fact that rebinding this is inherently bad. Rather they’d prefer not to have to do it every time they create an event handler. It would, after all, seem to be adding unnecessary boiler plate to the code.

 

Get to know the beast.

So what is this bind() and why do we need it? When I first started understanding the problem I began by taking a look at the MDN docs for the bind function. The part I’ve linked there should also aid in your own understanding of why the bind call is necessary.

Essentially, it is necessary so that no matter where the event handler is called from we can rely on the instance of this to be pointing at our component, which has things like state on it. Because we often operate on state in our event handlers it’s useful for us to have a reference to the component where these component related properties live.

Let’s learn by tinkering shall we? To illustrate the problem, roll yourself up a new create-react-app pipeline and copy paste the component below over the top of the generated App.js:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this);
let count = this.state.count;
count++;
this.setState({
count
});
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
<div>{this.state.count}</div>
<button onClick={this.handleClick}>Click Me</button>
</p>
</div>
);
}
}
export default App;

All we have is the basic CRA App.js except that I’ve changed the body text to be a counter display and a button that calls to a handler function which updates state, so the counter goes up with every click of the button.

Currently this component works and if you run it and look in the console then you’ll see that when you click the button the component is logging out the value of this. You should see that was is being logged out is the App component object. This is because we are binding the this that is being used in the handleClick handler to the App component.

As an experiment though, why don’t you try removing the bind function call on line 13 and then try clicking the button again and observing the result in the console. See how we now have a null reference to this? That is because the function you are calling is not, itself, a class and so the default behaviour for javascript is to leave this as being uninitialised.

 

Down with boilerplate!

A number of newcomers to React find that having to rebinding this for every event handler they create leaves a bad taste in their mouth………tastes like boilerplate..yuk!

Up until now I’ve not really had a lot the I could say to make them feel any better about this situation other than

  1. It’s not really React’s fault that we have to do this; and
  2. It’s not really that big a deal because ideally you wouldn’t be building components with so many event handlers that this becomes a major problem. Because…Componetised UIs right?!

Other than that I have had to quietly agree with them that it is kind of sucky. BUT NO MORE! For I have discovered ES7+ Public Class Fields! Don’t worry if that link is just hopelessly confusing, I’ve only provided it for reference. I’ll explain to you it’s implications now.

With Public Class fields we’re able to declare properties on classes that can hold a function or other type and because the property is declared directly on the Class the this variable is bound correctly to the class itself and is ready for use within the property. Let’s take a look at what this new syntax looks like:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
state = {
count: 0,
};
handleClick = () => {
console.log(this);
let count = this.state.count;
count++;
this.setState({
count
});
};
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
<div>{this.state.count}</div>
<button onClick={this.handleClick}>Click Me</button>
</p>
</div>
);
}
}
export default App;

See the differences? Do you think it looks as sweet as I do? Let’s run through what I’ve done here.

First of all we no longer need a constructor, because all we were doing in the constructor was initialising state and binding the event handler. But with this new syntax we can do both of these things by just declaring them as Public Class Fields.

In this new syntax state get’s declared and initialised directly on the class itself ! Also you should be able to see that we are declaring handleClick as a property whose value is the definition of our handler function. If you copy this code into the App.js of your CRA build from before you’ll see that this works the same way as the first snippet above and outputs to console. But the syntax just looks so much sexier doesn’t it?! And nary a call to bind in sight.

 

These are a few of my [new] favourite things

There you have it, a great way to avoid having to make a bind call for every event handler in your React application. The best part about all this is that even though this is an ES7+ feature, babel makes it available for you to use now! You’ll notice in the CRA Readme that it already has the Class fields stage 2 proposal module of Babel built in.

As a disclaimer: Stage 2 means that the proposal to include this functionality in future versions of ECMAScript has passed through the public “do we want this” sort of phase and the specification is now being drafted. That means that this functionality is definitely coming but it’s exact syntax isn’t quite nailed down yet.

But, really,  if CRA are confident enough in it to be including it their build pipeline today then I think gives me enough confidence to start using it as well. Also, I can’t imagine that this particular syntax could go down too many odd routes that would see you making major changes to amend your code.

So there it is; what I learned at my Hackathon. Fair old gem don’t you think? Tell me what you think about this revelation in the comments below or on any of my social medias above. Are you excited about how much this information is going to change your React development or are you dismayed that I hadn’t heard of this till now? Let me know.