How calling a callback directly fixes the 'this' in a React Class Component?

左心房为你撑大大i 提交于 2021-01-28 00:37:47

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!