简体   繁体   中英

How do i call a method within another method in react class Es6

So what i'm basically trying to do is simple

class Something extends React.Component {

validateEmail () {
//code that validates email,innerHTML a div.status element if error occurs
this.removeStatus();//then remove status onkeydown of input element
 }

removeStatus () {
//code that removes the status onkeydown of input element

 }
}

for some reason it's not working. in my javascript console (chrome) i'm getting this

login.js:132Uncaught TypeError: this.removeStatus is not a function

Edit 1: I've added the actual code, as you can see i'm binding validateEmail in the constructor

class Email extends React.Component {
constructor(props) {
      super(props);
      this.change = this.change.bind(this);
      this.validateEmail = this.validateEmail.bind(this);
      this.state = {
        value : ''
      }
    }
removeStatus() {
$('input').on('keydown',function () {
    $('.contextual-info').fadeOut();
});
}

 validateEmail(event) {
event.preventDefault();
var token = $('#token').val();
var email_regex=/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
if ($.trim(this.state.value)  !== "") {
    if (email_regex.test(this.state.value)) {
        $.ajax({
            url:'/login',
            type:'post',
            data:{email:this.state.value,_token:token},
            success: function (response) {
            if (response) {
                $('#email').remove();
                $('.btn').remove();
                $('#status').html('');
                ReactDOM.render(<Password /> ,document.getElementById('login-dialogue'));
                $('input[type="password"]').focus();
                }  else {
                $('input#email').addClass('input-context');
                if($('#status').html('<div class="bg-danger contextual-info wrong">Email Address Not Found!</p>')){
                    this.removeStatus();
                    }
                }
            }
        });
    } else {
    if($('#status').html('<div class="bg-danger contextual-info wrong">Invalid Email Address</div>')){
        this.removeStatus();
    }
    }
} else {
    if($('#status').html('<div class="bg-danger contextual-info wrong">Can\'t submit an empty field!</div>')){
        this.removeStatus();
    }
}
}
change (event) {
this.setState({
    value : event.target.value
    });
}

render(){
    return(
        <div className="login-dialogue" id="login-dialogue">
        <h1 className="text-center">Log in</h1>
        <div id="status"></div>
        <form action="" onSubmit={this.validateEmail} id="validateEmail">
        <input type="email" id="email" value={this.state.value} placeholder="Email Address" onChange={this.change} />
        <button type="submit" className="btn btn-flat btn-wide teal white-text">Continue</button>
        </form>
        </div>
        );
}

}
 ReactDOM.render(<Email /> ,document.getElementById('flex-me'));

Your methods are defined properly, so the problem is in how you call validateEmail .

You're invoking it in a way that sets this to something other than your Something instance. This is common in event listeners. I guess you have some code like this in your render :

<button onClick={this.validateEmail} /> 

The recommended solution for React is to bind event handlers in your constructor:

class Something extends React.Component {

  constructor() {
    super();
    this.validateEmail = this.validateEmail.bind(this);
  }

  // ...
}

You could also call the method from inside an arrow function, which preserves the value of this at the place it was declared:

<button onClick={() => this.validateEmail()} /> 

The disadvantage of this approach is that a new onClick handler is created each time your component is rendered.


EDIT : same problem, different place. You call removeStatus inside a function , which loses the outer this binding. Use an arrow function instead:

$.ajax({
  success: (response) => { 
    // etc
    this.removeStatus();
  }
})

Further reading:

I had a similiar Problem

I just ran into a similar problem with the same error message. What is weird is that sometimes when i call a method inside another method it works. I am making a Simon game and the following method in a method works.

handleMouseDown (e) {
    if(e.target.id==="green"){
    $("#green").addClass("colorGreenPush");
      greenSound.play();
      clicked.push(1);
      this.handleCheck();
    } 

I am simply running a check method when the user presses a button. No error.

However I was getting a TypeError with this code

 handleCheck () {
    var display = $("#display");
    if(litID.length == clicked.length){
      if(litID.join() == clicked.join()){
        if(round == 20){
          setTimeout(function(){
          alert("Unreal. You Acually Won!!!");
          location.reload();
          },1000);
        }
        else{
          setTimeout(function(){
            display.text("-"+(round + 1)+"-");
            round ++;
            console.log(this);
            litID = [];
            clicked = [];
            j = 0;
            this.handleGame();
          },1000);
        }
      } 

Near the end I try this.handleGame(); and it wasn't working.

My Solution

You will notice I did a console.log(this); just to see what this was at this point. Turns out this was the Window Object. I don't know why, perhaps being buried in if/else statements. Both methods are binded so that wasn't the problem.

Anyhow. I went poking around in the window object and turns out that i can use this.App.prototype.handleGame(); and it works! I should add that the name of my main ES6 Component is App. This will vary based on your component and method names, but the overall principle should still apply.

开发工具截图

I Am In Shock

I'll admit I am a newb. This is my second mini project in React but finding this was the coolest thing. Now there may be other ways like the arrow functions mentioned above, but this is what worked for me. And it was the difference between having a game and having straight garbage. Hope this helps someone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM