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",
...
}