Understanding 'this' in React Components

Understanding 'this' in React Components

Posted by Leonard Meng on November 15, 2023

React

React, a popular JavaScript library for building user interfaces, often involves handling the this keyword, especially in class components. Understanding how this behaves in different contexts is crucial for React developers. In this article, we’ll explore the behavior of this in React, using a class component example that demonstrates a common scenario.

Class Components and this

In React class components, this refers to the instance of the component. This is crucial for accessing state, props, and class methods. Consider the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Weather extends React.Component {
    constructor(props) {
        super(props);
        // Initialize state
        this.state = { isHot: false };
    }

    render() {
        // Read state
        const { isHot } = this.state;
        return <h1 onClick={this.changeWeather}>Today's weather is {isHot ? 'hot' : 'cool'}</h1>;
    }

    changeWeather() {
        // Where is changeWeather located?
        // On the prototype object of Weather, for instance use
        // Since changeWeather is a callback for onClick, it's not called through the instance directly
        // When changeWeather is called through a Weather instance, 'this' inside it refers to the Weather instance
        // Methods in the class default to strict mode, so 'this' inside changeWeather is undefined
        console.log(this);
    }
}

// Render the component to the page
ReactDOM.render(<Weather />, document.getElementById('test'));

In the above example, this within the changeWeather method should ideally refer to the component instance. However, there’s a catch.

The Problem with this

When changeWeather is used as an onClick event handler, its context changes. In JavaScript, the value of this is determined by how a function is called, not

where it is defined. Since changeWeather is used as a callback and not called directly as a method of the Weather instance, this does not refer to the component instance, leading to unexpected behavior — typically, this will be undefined.

This is not specific to React but is a part of how JavaScript functions work. In class components of React, this behavior can lead to bugs, especially when trying to access this.state or this.props inside these callbacks.

Why Does This Happen?

The root cause of this problem lies in JavaScript’s handling of this inside functions. In JavaScript, the value of this inside a function depends on the function’s execution context. When a method like changeWeather is passed as a callback, JavaScript doesn’t automatically bind the context of the component instance to it.

Solutions in React

React offers several ways to handle this issue:

1. Binding in the Constructor:

One common solution is to explicitly bind the method to the component instance in the constructor.

1
2
3
4
5
constructor(props) {
    super(props);
    this.state = { isHot: false };
    this.changeWeather = this.changeWeather.bind(this);
}

By doing this, changeWeather will always have this referring to the component instance, regardless of how it’s called.

2. Arrow Function in Render:

Another approach is to use an arrow function in the render method:

1
2
3
render() {
    return <h1 onClick={() => this.changeWeather()}>Today's weather is {this.state.isHot ? 'hot' : 'cool'}</h1>;
}

Arrow functions don’t have their own this context, so this refers to the enclosing lexical context, which is the component instance in this case.

3. Class Properties as Arrow Functions:

A modern and increasingly popular approach is to define the method as an arrow function in the class property:

1
2
3
4
5
6
7
8
9
10
11
12
class Weather extends React.Component {
    state = { isHot: false };

    changeWeather = () => {
        console.log(this);
        // Rest of the method
    };

    render() {
        return <h1 onClick={this.changeWeather}>Today's weather is {this.state.isHot ? 'hot' : 'cool'}</h1>;
    }
}

In this approach, changeWeather is automatically bound to the instance of the class, so this will always refer to the component.

Conclusion

Understanding the behavior of this in React class components is key to writing bug-free code.

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Welcome to reprint, and please indicate the source: Lingjun Meng's Blog Keep the content of the article complete and the above statement information!