Parnab Sanyal
Parnab Sanyal

Reputation: 739

Can not understand context of this in the code example

In the below code snippet I am unclear on how this is being managed by React.

class Main extends React.Component {
    private name: string

    constructor(props: any) {
        super(props)
        this.name = 'heisenberg'
    }
    render() {
        return (
            <div>
                {this.sayMyName()}
                <button onClick={this.sayMyName}>Say My Name</button>
            </div>
        )
    }
    sayMyName(): string {
        return this.name
    }
}

It is first printing heisenberg in the page and when I am clicking the button it saying this is undefined, which is clear to me, that React does not automatically bind this to all the methods.

So, how exactly the context is getting changed once I am invoking the sayMyName method from directly inside {} and then from button click.

Adding screenshot

Before Button Click enter image description here

After Button Click enter image description here

Upvotes: 2

Views: 70

Answers (2)

Demon
Demon

Reputation: 826

https://medium.freecodecamp.org/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb

This person does a good article on your question. Basically, he's saying you can blame how JavaScript is like that.

In short, this context isnt lost... it more or less pointing to the global object

Upvotes: 2

Nicholas Tower
Nicholas Tower

Reputation: 84902

An onclick event is asynchronous. When the callback is called, it's called from a global context, so this is set to the window object in non-strict mode, or undefined in strict mode.

To fix this, either create an arrow function in the render method (arrow functions take their value of this from the context in which they are defined), and pass that in to the button:

<button onClick={event => this.sayMyName(event)}>Say My Name</button>

Or create a bound version of sayMyName

constructor(props: any) {
    super(props);
    this.name = 'heisenberg';
    this.sayMyName = this.sayMyName.bind(this);
}

Upvotes: 6

Related Questions