Home > Software design >  value of this inside the eventHandler in class based component
value of this inside the eventHandler in class based component

Time:05-20

I am new to the React and little confused here


export default class Message extends Component {

    m1() {
        console.log("Hello world");
    }
    render() {
        return (
                <button className="btn btn-primary" onClick={this.m1}>Click 1</button>
        );
    }
}

Why value of this is not the button element itself?

Why it refer to the caller object ?

CodePudding user response:

value of this inside the eventHandler in class based component

As described in the documentation here, React doesn't do anything to set this to any specific value, so if you do onClick={myFunction}, it's equivalent to calling myFunction(event). In JavaScript, calling a function that way uses the default this value, which is undefined in strict mode (class code is always strict). This is different from how addEventListener works, where the DOM event system sets this to the element the event handler is attached to when calling the function.

Why value of this is not the button element itself?

A design choice by the React team. If you want the element that the event handler was attached to, you can get it from the event object your handler is passed using event.currentTarget (this is also true with addEventHandler handlers in non-React code; this and event.currentTarget have the same value by default).

Why it refer to the caller object ?

It doesn't. If you mean how can you make it refer to the instance of the class component, see this question's answers. The usual solutions are to use bind on the event handler function, or to use a wrapper arrow function (more in this question's answers).

For instance, re your code, you might bind m1 in your constructor:

export default class Message extends Component {
    constructor(props) {                // ***
        super(props);                   // ***
        this.m1 = this.m1.bind(this);   // ***
    }                                   // ***
    m1() {
        console.log("Hello world");
    }
    render() {
        return (
                <button className="btn btn-primary" onClick={this.m1}>Click 1</button>
        );
    }
}

Or, you might just do a wrapper arrow function where you call it:

return (
        <button className="btn btn-primary" onClick={(event) => this.m1(event)}>Click 1</button>
        {/* −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^    */}
);

Or, some people assign an arrow function to a class field instead of using method syntax:

export default class Message extends Component {
    m1 = () => {                    // ***
        console.log("Hello world"); // ***
    };                              // ***
    render() {
        return (
                <button className="btn btn-primary" onClick={this.m1}>Click 1</button>
        );
    }
}

I'm not a fan of that because it means the method isn't on the prototype, which is handy for several reasons (including mocking for tests), but it's an option.

CodePudding user response:

onClick={this.m1}

The value between { and } is an expression that is evaluated when the function it is inside (render() in this case) is called.

So the value of this from the scope of render() and depends on how render() is called (exceptions for bind, arrow functions, etc aside).

In this case, the result of the expression is the function m1 which is assigned to the onClick prop of the button component.


This is different from the HTML onclick attribute which accepts a string representing a function body which is evaluated when the client event fires.

  • Related