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:
this
on MDNI 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.
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.
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'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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With