React React.createClass vs extends React.Component "this" Context


Example

Using React.createClass will automatically bind this context (values) correctly, but that is not the case when using ES6 classes.

React.createClass

Note the onClick declaration with the this.handleClick method bound. When this method gets called React will apply the right execution context to the handleClick.

import React from 'react';

const MyComponent = React.createClass({
  handleClick() {
    console.log(this); // the React Component instance
  },
  render() {
    return (
      <div onClick={this.handleClick}></div>
    );
  }
});

export default MyComponent;

React.Component

With ES6 classes this is null by default, properties of the class do not automatically bind to the React class (component) instance.

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  handleClick() {
    console.log(this); // null
  }
  render() {
    return (
      <div onClick={this.handleClick}></div>
    );
  }
}

export default MyComponent;

There are a few ways we could bind the right this context.

Case 1: Bind inline:

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  handleClick() {
    console.log(this); // the React Component instance
  }
  render() {
    return (
      <div onClick={this.handleClick.bind(this)}></div>
    );
  }
}

export default MyComponent;

Case 2: Bind in the class constructor

Another approach is changing the context of this.handleClick inside the constructor. This way we avoid inline repetition. Considered by many as a better approach that avoids touching JSX at all:

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    console.log(this); // the React Component instance
  }
  render() {
    return (
      <div onClick={this.handleClick}></div>
    );
  }
}

export default MyComponent;

Case 3: Use ES6 anonymous function

You can also use ES6 anonymous function without having to bind explicitly:

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  handleClick = () => {
    console.log(this); // the React Component instance
  }
  render() {
    return (
      <div onClick={this.handleClick}></div>
    );
  }
}

export default MyComponent;