Seun LanLege Seun LanLege - 1 month ago 6
Javascript Question

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'));

Answer

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:

Comments