Class properties in Javascript are a nice addition which can save a bit of verbose boilerplate. For instance, if you have a lot of event handlers in a class which need to access this, you need to make sure you bind the class in the constructor:

class Homepage extends React.Component {
  constructor (props) {
    this.state = {
      toggled: false
    };

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick (e) {
    console.log(e.target.value);

    const { toggled } = this.state;
    this.setState({ toggled: !toggled });
  }
}

If you have a few handlers in your class, then this boilerplate gets pretty tedious to keep writing out.

Babel plugin

You can avoid this boilerplate by using class properties: they allow you to use arrow functions as class members, which automatically bind this from context. That means any arrow function member doesn’t have to have the .bind(this) boilerplate in the classes’ constructor.

Class properties are still only a proposal at the moment, but Babel has a plugin which can transform your code: @babel/plugin-proposal-class-properties.

Setup

npm i --save-dev @babel/plugin-proposal-class-properties

Then add the plugin to your .babelrc file. If your project is using Gatsby, you’ll need to create a custom .babelrc file and add the babel-preset-gatsby plugin as well to avoid breaking Gatsby’s build process.

// .babelrc
{
  "plugins": ["@babel/plugin-proposal-class-properties"],
  "presets": ["babel-preset-gatsby"] // only if you're using Gatsby
}

This allows you to do fun things like use arrow functions as class members, which are automatically bound to the class:

class Homepage extends React.Component {
  state = {
    toggled: false
  };

  handleClick = e => {
    console.log(e.target.value);

    const { toggled } = this.state;
    this.setState({ toggled: !toggled });
  }
}

If you’re using eslint, then you’ll need to use babel-eslint as the parser instead to prevent lint errors. Install babel-eslint

npm i --save-dev babel-eslint

and then update your .eslintrc file:

{
  "parser": "babel-eslint",
  ...
}

Would you like to know more?