Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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'));
like image 244
Seun LanLege Avatar asked Oct 15 '16 18:10

Seun LanLege


2 Answers

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:

  • this on MDN
  • React "reusable components" docs
like image 54
joews Avatar answered Sep 22 '22 19:09

joews


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.

Dev Tools Screenshot

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.

like image 33
benjaminadk Avatar answered Sep 22 '22 19:09

benjaminadk