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.