DEV Community

Cover image for Understanding "this" in React
Akhila Ariyachandra
Akhila Ariyachandra

Posted on • Updated on • Originally published at akhilaariyachandra.com

Understanding "this" in React

PS - This was originally post in my blog. Check it out if you want learn more about React and JavaScript!

this in JavaScript can confusing as it can change based on where it is called from. In this post I'll try to clear it up.

The JavaScript "this" keyword refers to the object it belongs to. 1

To clearly understand how this can change let's look at the places it can be called from.

"this" alone

const test = this
console.log(test) // global variable
Enter fullscreen mode Exit fullscreen mode

this accessed outside a function will return the global variable.

"this" in a function

function foo() {
  console.log(this) // undefined in “strict mode” or the global variable
}
Enter fullscreen mode Exit fullscreen mode

If we access this inside a function (cannot be a method), it'll be the global variable and in "strict mode" it'll be undefined.

"this" in a method

const user = {
  firstName: "Akhila",
  lastName: "Ariyachandra",
  fullName: function() {
    return this.firstName + " " + this.lastName
  },
}

console.log(user.fullName()) // Akhila Ariyachandra
Enter fullscreen mode Exit fullscreen mode

When this is accessed in a method, it refers to the owner of the method, which is the object it's in.

"this" in an inner function

const user = {
  firstName: "Akhila",
  lastName: "Ariyachandra",
  fullName: function() {
    return this.firstName + " " + this.lastName
  },
  innerFunction: function() {
    function testFunction() {
      return this.firstName + " " + this.lastName
    }

    return testFunction()
  },
}

console.log(user.innerFunction()) // undefined undefined
Enter fullscreen mode Exit fullscreen mode

Here this changes inside testFunction(). In order to understand why we need to know how scope applies to this.

Unlike variables, the this keyword does not have a scope, and nested functions do not inherit the this value of their caller. If a nested function is invoked as a method, its this value is the object it was invoked on. 2

This means that the this of testFunction() is not aware of the user object so it returns undefined for this.firstName and this.lastName.

So how do we get the proper "this" into the inner function?

Before ES5

const user = {
  firstName: "Akhila",
  lastName: "Ariyachandra",
  innerFunction: function() {
    const that = this
    function testFunction() {
      return that.firstName + " " + that.lastName
    }

    return testFunction()
  },
}

console.log(user.innerFunction()) // Akhila Ariyachandra
Enter fullscreen mode Exit fullscreen mode

Before ES5 there was no proper way to pass this to inner functions. The example shown around is a workaround. 3

ES5

const user = {
  firstName: "Akhila",
  lastName: "Ariyachandra",
  innerFunction: function() {
    function testFunction() {
      return this.firstName + " " + this.lastName
    }

    testFunction = testFunction.bind(this)

    return testFunction()
  },
}

console.log(user.innerFunction()) // Akhila Ariyachandra
Enter fullscreen mode Exit fullscreen mode

ES5 introduced the bind method, which allows us to set the this of the function. So after we run the line testFunction = testFunction.bind(this), the this of testFunction() becomes the user object.

ES6+

const user = {
  firstName: "Akhila",
  lastName: "Ariyachandra",
  innerFunction: function() {
    const testFunction = () => {
      return this.firstName + " " + this.lastName
    }

    return testFunction()
  },
}

console.log(user.innerFunction()) // Akhila Ariyachandra
Enter fullscreen mode Exit fullscreen mode

ES6 brought us arrow functions, which automatically binds this to the function, which leads to less and cleaner code.

So what about React?

Consider the following code.

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      text: "",
    }
  }

  setText() {
    this.setState({ text: "Hello World!" })
  }

  render() {
    return (
      <div>
        <h1>{this.state.text}</h1>
        <button onClick={this.setText}>Set Text</button>
      </div>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

It'll fail once we click the button and code reaches the this.setState({ text: "Hello World!" }); line. Why? Because at that point this will be undefined. this wasn't implicitly bound to setText() so it defaults to the global variable which in this case is undefined because classes run in "strict mode". Since this wasn't implicitly bound, we need to explicitly bind this to setText().

We could solve this by using the way we did it the before ES5 example but that's stringly discouraged. If we did it with bind, it would look like this.

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      text: "",
    }
    this.setText = this.setText.bind(this)
  }

  setText() {
    this.setState({ text: "Hello World!" })
  }

  render() {
    return (
      <div>
        <h1>{this.state.text}</h1>
        <button onClick={this.setText}>Set Text</button>
      </div>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

If you use bind, you'll have to do it in the constructor.

Arrow functions can make it easier by just needing to change setText() to an arrow function.

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      text: "",
    }
  }

  setText = () => {
    this.setState({ text: "Hello World!" })
  }

  render() {
    return (
      <div>
        <h1>{this.state.text}</h1>
        <button onClick={this.setText}>Set Text</button>
      </div>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

References


  1. w3schools.com, The JavaScript this Keyword

  2. David Flanagan, JavaScript: The Definitive Guide 

  3. amitai, Using "this" in react functions 

Top comments (2)

Collapse
 
macsikora profile image
Pragmatic Maciej

I didn't know React I a language ;) . The title is or a click bait or you try to create a confusion for devs who learn JS and React.

I can answer how this works in React in rhe one line:
It works like in JavaScript

Collapse
 
michaeljota profile image
Michael De Abreu

In his defense, people doesn't want to learn JS, just React or Vue or _Angular, or whatever they are using. :/.