2 minutes read 16th October, 2016
programming

The problem

After working with React and ES6 for a couple of projects I quickly got tired of binding this to my functions in the constructor of my components. If you use React.createClass it will autobind this as the component to all your functions but if you use ES6 classes that extend React.Component then those functions won’t be bound to the component.

This becomes a chore as generally the functions you place on a component all use this.props, this.state or this.setState(). Think event handlers for the component, functions to update state on HTTP requests, that kind of thing. In fact I wonder if a function isn’t using props or state then perhaps it doesn’t belong on that component. Anyway there’s a good article on the different methods of binding this to your component methods and I found none of them particularly satisfactory.

Here’s how I used to write components:

const React = require('react');

class Component extends React.Component {
  constructor(props) {
    super(props);

    this.onClick = this.onClick.bind(this);
    this.onChange = this.onChange.bind(this);
  }

  onClick(event) {
    this.setState({ /* some new state */ });
  }

  onChange(event) {
    this.setState({ /* some new state */ });
  }

  // the rest of the component
}

This sucks. You have to remember to bind every. single. method. If you forget then you get an irritating “setState doesn’t exist on undefined” (or props or state). When removing methods you have to remember to remove the bind code from the constructor lest you get errors about binding something that doesn’t exist.

There are all the other options listed both in the article as well as the react official docs but they all require me doing things. I want the old React.createClass behaviour with ES6 classes.

A wrapper for React’s component

I decided to just write a wrapper class for React’s Component. I call it, Component. Here it is:

const React = require('react');

module.exports = class Component extends React.Component {
  constructor(props) {
    super(props);

    Object.getOwnPropertyNames(Object.getPrototypeOf(this))
      .filter(property => typeof this[property] === 'function')
      .forEach(property => {
        this[property] = this[property].bind(this);
      });
  }
}

To use it just require and extend Component instead of React.Component. You will have to require React still for things like prop types. Here’s how I write components now:

const React = require('react');
const Component = require('./component.js');

class Component extends Component {
  onClick(event) {
    this.setState({ /* some new state */ });
  }

  onChange(event) {
    this.setState({ /* some new state */ });
  }

  // the rest of the component
}

And it’s just like having React.createClass back.