Why do we need to bind methods inside our class component’s constructor?
Tags: react, javascript, webdev
Published: 2019-08-19 09:30:09

If we go back into the time where the [hooks](https://reactjs.org/docs/hooks-intro.html) were not yet born, we will inevitably encounter this code while creating a React class [component](https://reactjs.org/docs/components-and-props.html#function-and-class-components). 

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

    // Assuming that you need to pass this as a prop to one of a child component
    this.someMethod = this.someMethod.bind(this); // But why? 🤔
  }
 ... 
}
```

This is because whenever inside a class component when we need to pass a function as props to the child component, we have to do one of the following:

- Bind it inside the constructor function.
- Bind it inline (which can have some performance issues).
- Use [*arrow function*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) (which is the same as [*property initializer*](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties) syntax).

Have you ever wondered why it has to be this way? Why we have to do this extra piece of work?

Through this article, I will first try to explain the binding inside the constructor function. Once we acquire that knowledge, we will try to answer why arrow functions don’t follow the same ceremony.

One thing we need to know that binding in the constructor has nothing to do with React. It’s purely related to how JavaScript implements **this**. Let’s look at the following code:

```javascript
var x = 10;
let foo = {
  x: 90,
  getX: function() {
    return this.x;
  }
};

foo.getX(); // prints 90

let xGetter = foo.getX;

xGetter(); // prints 10;
```

When we initialised *x* into a global scope, it becomes the property of the *window* object (assuming that it’s a browser environment and not a strict mode). We can assert that:

```javascript
window.x === 10; // true
```

**this** will always point to the object onto which the method was invoked. So, in the case of *foo.getX()*, **this** points to *foo* object returning us the value of 90. Whereas in the case of *xGetter()*, **this** points to *window* object returning us the value of 10.

To retrieve the value of *foo.x*, we can create a new function by binding the value of **this** to *foo* object using [Function.prototype.bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind).

```javascript
let getFooX = foo.getX.bind(foo);
getFooX(); // prints 90
```

Armed with this knowledge, let’s try to understand what happens when you pass a function prop into the child component.

In the following code example, we have created a dummy *class* component to mimic React Component mental model. Inside the *render* function, we are returning a plain JS object which has a functional prop called *'onClick'*.

> The [React element](https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html#elements-describe-the-tree) is just an immutable description object with
> two fields: type: (string | ReactClass) and props: Object

```javascript
class Component {
  constructor() {
    this.state = 10;
    this.setState = function() {
      console.log('state');
    };
  }

  handleClick() {
    this.setState();
  }

  render() {
    // return a child component.
    return {
      type: 'button',
      props: {
        // pass functional props
        onClick: this.handleClick,
        children: 'Click Me'
      }
    };
  }
}

// 1. creating a component instance
const componentInstance = new Component();

// 2. calling a render method on the instance
// ( In reality, React does the same thing for your class components)
const element = componentInstance.render();

// 3. calling the onClick function, which was passed as a  prop,
// will throw a 'TypeError: this.setState is not a function'.
element.props.onClick();
```

This TypeError is obvious now because this is pointing to the *props* object which doesn’t know the existence of any setState function. The *setState* function is only a property of *componentInstance*.

So, to fix this problem, we have to bind the handleClick function inside the constructor:

```javascript
// inside constructor function
constructor() {
  // bind returns a new function
  this.handleClick = this.handleClick.bind(this);
}

...

// calling onClick will print 'state' this time.
element.props.onClick();
```


Now, the value of **this** will always point to *componentInstance* which has *setState* as one of its property and it will not throw any TypeError.

---

Now, that was the answer to our first question. It’s good progress so far. Moving forward, we shall try to find out the answer to our second question.

Looking at the code below:

```javascript
let bar = { someMethod: function() { return this; } };

bar.someMethod(); // print {someMethod: f}

let foo = { someMethod: () => this};

foo.someMethod(); // prints global 'window' object
```

shows that arrow functions have no this of their own. It is always determined by the scope surrounding the arrow function when it was created.

> Arrow functions have no _this_ of their own.

When we use an *arrow* function inside our class (using [property initializer](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties) feature), it becomes the method property of the instance. As **this** will always be determined by the outer scope, it will point to the *instance* of the class. Let’s see that in action:

```javascript
class Component {
  constructor() {
    this.state = 10;
    this.setState = function() {
      console.log('state');
    };
  }

  // using fat arrow function; no binding require inside constructor
  handleClick = () => {
    // this will now point to the instance of Component class which knows about the setState method property
    this.setState();
  };

  render() {
    // return a child component.
    return {
      type: 'button',
      props: {
        // pass functional props
        onClick: this.handleClick,
        children: 'Click Me'
      }
    };
  }
}
// 1. creating a component instance
const componenttInstance = new Component();

//  2. calling a render method on the instance ( In reality, React does the same thing for your class components)

const element = componenttInstance.render();

// 3. calling onClick will now print 'state' to the console.
element.props.onClick();
```


I hope you have enjoyed reading this article and now will be able to answer the question confidently. I highly recommend reading this [article](http://2ality.com/2017/12/alternate-this.html) by [Dr. Axel Rauschmayer](https://twitter.com/rauschma) for a more detailed description of how `this` works.

Thank you for reading, and if you liked the article a few ❤️ will definitely make me smile 😍.