Im noob with React and trying to create a login form. When the user enters correct login informations a rest api will return JWT token. However i cant find how to set the state "token" to be the value of the response. Still i can save the response.token to localstorage and it shows correctly. I think the "this" points to wrong function, but how could i get around this without breaking the logic? Any hints? Thanks
Login.js
import React from 'react';
import axios from 'axios';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import MyInput from './../components/Input';
import { connect } from "react-redux";
import { Form } from 'formsy-react';
var server = "http://localhost:3000";
class Login extends React.Component {
constructor(props) {
super(props)
this.state = {
canSubmit: false,
token: null
};
this.enableButton = this.enableButton.bind(this);
this.disableButton = this.disableButton.bind(this);
this.submit = this.submit.bind(this);
}
submit(data) {
axios.post(server + '/login', {
username: data.username,
password: data.password
})
.then(function (response) {
if (response.data.token) {
var token = response.data.token;
localStorage.setItem("token", token);
this.setState({ token: token }); //Here is the problem
console.log(this.state.token);
} else {
location.reload();
}
});
}
enableButton() {
this.setState({ canSubmit: true })
}
disableButton() {
this.setState({ canSubmit: false })
}
render() {
return (
<div className="loginForm">
<h2 className="page-header">Login</h2>
<Form onSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton}>
<div className="form-group">
<label>Username: </label>
<MyInput name="username" validations="isExisty" validationError="Required" required />
</div>
<div class="form-group">
<label>Password: </label>
<MyInput type="password" name="password" validations="isExisty" validationError="Required" required />
</div>
<button
type="submit"
className="btn btn-primary"
disabled={!this.state.canSubmit}>
Login
</button>
</Form>
<br/>
<a href="register">Create user!</a>
<a id="forgot" href="forgot">Forgot password?</a>
</div>);
}
}
export default Login;
TypeError: Cannot read property 'setState' of undefined ReactJS The solution. The issue happens because the method is not properly bind with this. As we all know that when we create a function it has it’s own special object this. As the arrow function does not have any special object this.
Use the ES6 syntax for the big arrow function. It automatically binds the “this” keyword to that method so you don’t have to bind it in the constructor: There you have it! That’s how you get rid of the “this.setState” is “undefined” or “not a function” error when using the class component structure in React.
The issue happens because the method is not properly bind with this. As we all know that when we create a function it has it’s own special object this. As the arrow function does not have any special object this. This problem can be solved with the arrow function like below: Here is a good article about bind of ReactJS component classes.
These errors occur because the method you are using or invoking in your React Component is not bound correctly. Here is an example of code that will cause the error to happen (This assumes that you have your React component set up correctly):
You can use an arrow function to keep the context of submit
and be able to access to setState
:
submit(data) {
axios.post(server + '/login', {
username: data.username,
password: data.password
})
.then((response) => {
if (response.data.token) {
var token = response.data.token;
localStorage.setItem("token", token);
this.setState({ token: token });
console.log(this.state.token);
} else {
location.reload();
}
});
}
As Alexander stated in the comment, I must use the arrow function =>
or set this
for callback.
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