Use Arrow function, () => {}, to correctly bind this
Tags: webdev, javascript, beginners
Published: 2022-04-25 09:32:40

As part of my role working for [AG Grid](https://ag-grid.com/javascript-data-grid/) I get to see a number of repeated issues. One such issue that I have seen multiple times is this.

> `this.props` is `undefined` in a callback but I know that it does have a value in my component!
 
## What is `this`?

Let's look at an example of when this can easily occur. Below is a section of the code for a [Bar Chart](https://www.ag-grid.com/react-charts/events/#example-nodeclick-event) which has added a click event listener.

This example is written in React but you will experience the same in Angular, Typescript and any Class based code.

```jsx
class ChartExample extends Component {
  constructor(props) {
    super(props);

    this.state = {
      options: {
        series: [
          {
            listeners: {
              nodeClick: function (event) {
                // Do something with our props
                console.log("Props are:", this.props)
              },
            },
          },
        ],        
      },
    };
  }

  render() {
    return (
      <div className="wrapper">
        <AgChartsReact options={this.state.options} />
      </div>
    );
  }
}

render(<ChartExample test={'Test Value'} />, document.querySelector('#root'));
```

The key part of this code is the following section where we define our listeners.

```ts
 listeners: 
  {
    nodeClick: function (event) {
        // Do something with our props
        console.log("Props are:", this.props)
    }
  }
```

If our component receives `props` then we would expect that these would be logged to the console. However the above code logs `undefined` when a node is clicked. You can confirm this for yourself in this [Plunker](https://plnkr.co/edit/Kna1PZpJ1gcXQsXg?open=index.jsx&preview).


![this.props is undefined within function callback](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pqvzdqskztbybzh5dwx5.png)

## The arrow function fix

If we make what seems like a purely syntax change, swapping out the function definition for the equivalent arrow format, then try again, suddenly our props are now correctly logged to the console! Updated [Plunker](https://plnkr.co/edit/oODERaLUmamrCb1d?open=index.jsx&preview)

 ```ts
 listeners: {
              nodeClick: (event) => {
                // props are defined
                console.log("Props are:", this.props)
              },
            },
 ```

![this.props correctly defined within an arrow function callback](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zd0sby1u09pqmaip4kgh.png)

 So what is going on here and why does using the syntax `(event) => {}` suddenly make `this.props` have the correct value!?

## This binding with arrow function

The short answer to why this is works is that by default arrow functions bind `this` to the value in their surrounding scope. So in our example `this` will be correctly bound to our component class meaning that `this.props` will be correctly defined. When we use a standard `function` definition `this` is not bound to our component but instead will have the value of the class where our event was fired.

If you want to dive deeper into this topic I would recommend [Understanding Arrow Functions in JavaScript](https://www.digitalocean.com/community/tutorials/understanding-arrow-functions-in-javascript)

### Alternative Fix with bind

It is worth mentioning that you can also fix the original code by explicitly binding this when you define the callback. 

```ts
listeners: {
              nodeClick: function (event) {
                console.log("Props are:", this)                
              }.bind(this),
            },
```


## Conclusion

If you ever find yourself surprised that `this.props`, or for that matter, `this.anyClassProp` is undefined when you are expecting it to contain a certain value then you could check the context in which you are using `this`. You may find that simply updating a function definition to an arrow function resolves your issue.

As a result of these issues I have made a large update to all our AG Grid examples so that they use arrow functions by default to help avoid confusion for our users.