问题
I would like to learn how is the value of 'this' set when a function called in JSX as a callback to an eventHandler. I noticed that when I call it directly there is no issue accessing state without getting the famous undefined 'this' error, like so:
import React from "react";
class Accordion extends React.Component {
state = { term: "random term" };
onTitleClick() {
console.log("Title is clicked");
console.log(this.state.term);
}
render() {
const renderedItems = this.props.items.map((item) => {
return (
<React.Fragment key={item.title}>
<div className="title active" onClick={this.onTitleClick()}>
<i className="dropdown icon"></i>
{item.title}
</div>
<div className="content active">
<p>{item.content}</p>
</div>
</React.Fragment>
);
});
return <div className="ui styled accordion">{renderedItems}</div>;
}
}
export default Accordion;
When you pass it as just a reference, the famous 'this' is undefined error comes back. Then we know how to bind the 'this' and so on. I feel like I just memorized the solution and now would like to learn the difference.
回答1:
onClick={this.onTitleClick()}
- This is not how you set the event listener. You just need to pass the name of the function instead of calling it yourself.
As far as your question regarding the value of this
is concerned, value is set depending on how the function is called. This is not specific to React, this is just how value of this
is set in Javascript.
I noticed that when I call it directly there is no issue accessing state without getting the famous undefined 'this' error
That's because when you call it like this: this.onTitleClick()
- onTitleClick()
is called on this
which refers to the Accordion
component. But as mentioned at the start of this answer, this is not how you set the event listener. Instead of calling this method yourself, you need to let javasctipt call it.
When you pass it as just a reference, the famous 'this' is undefined error comes back
This is the correct way to add an event listener but you get an error because when javascript calls the event handler function, value of this
is not your component, i.e. Accordion
.
In case of React, this
inside the event handler function is null
but using vanilla javascript, this
inside an event handler is the HTML element on which the event listener was added. Keep in mind that this applies when you use the regular function as a event handler function.
To solve this issue, you have two options:
Explicitly set
this
using.bind()
this.onTitleClick = this.onTitleClick.bind(this);
Use arrow functions instead of regular functions as event handlers
onTitleClick = () => { console.log("Title is clicked"); console.log(this.state.term); }
Following are couple of related questions that might help in understanding this
further:
“this” is undefined inside an anonymous function returned by another function React
How does React share methods between classes(components)
回答2:
When you pass it as a reference, the this
is undefined. In order for this to work, you need to bind the function to the class. You can do that in the constructor
constructor(props) {
this.state = { term: "random term" };
this.onTitleClicked = this.onTitleClicked.bind(this);
}
Also, when you pass it to the component, don't call the function, just pass it
<div className="title active" onClick={this.onTitleClick}>
Notice missing parenthesis by the this.onTitleClick
call.
来源:https://stackoverflow.com/questions/64065090/how-calling-a-callback-directly-fixes-the-this-in-a-react-class-component