I am building a react login page that uses Django Rest Token authentication. I am at the process of creating error messages in the login page. But one of the errors I created is not displaying correctly. The error message is supposed to display after a user has clicked the login button (handleSubmit). But the error displays after the user additionally inputs a change (handleChange )in the input. I can't seem to trace where I did an error in my code. Some help would be appreciated. Thanks.
The error that does not display correctly is, it is in my code below, I enclosed it in ** so you could easily identify it. :-
{wrongcredentials ? <div className="errorMessage">Wrong username or password</div> : null}
Below is the core section of my code :
const formValid = ({formErrors, ...rest})=> {
let valid = true;
Object.values(formErrors).forEach(val =>{
val.length > 0 && (valid = false)
});
Object.values(rest).forEach(val =>{
!(val) && (valid = false)
});
return valid;
}
let isloading = false;
let wrongcredentials = false;
class Login extends Component{
constructor(props){
super(props)
this.state = {
credentials : {username :null, password :null},
formErrors :{
username :'',
password :'',
}
};
}
handleSubmit = e => {
e.preventDefault()
if(formValid(this.state)){
fetch('http://195.154.26.202:8000/auth/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(this.state.credentials)
}).then( data => data.json())
.then(
data => {
console.log('token', data.token)
if(data.token="undefined"){
console.error('wrong username or password')
wrongcredentials = true
}else{
window.location.href = '/';
isloading = true;
}
this.props.userLogin(data.token);
}
)
console.log(`
--SUBMITTING--
username: ${this.state.credentials}
password : ${this.state.credentials}
`)
}else{
console.error('FORM INVALID')
}
}
handleChange = e => {
e.preventDefault()
const cred = this.state.credentials;
cred[e.target.name] = e.target.value;
let formErrors = this.state.formErrors;
switch(e.target.name){
case 'username' :
formErrors.username = e.target.value.length>0 && e.target.value.length<3 ? 'minumum 3 characters required':
e.target.value.length==0? 'username is required': '';
break;
case 'password' :
formErrors.password = e.target.value.length>0 && e.target.value.length<6 ? 'minumum 6 characters required':
e.target.value.length==0? 'password is required': '';
break;
default:
break;
}
this.setState({credentials: cred}, ()=> console.log(this.state))
}
render() {
const {formErrors} = this.state
console.log('wrong', wrongcredentials)
return(
<div className="Login">
<div className="nav-bar">
<div className="title-section">
<h6>lobstr.io</h6>
</div>
</div>
<div className="wrapper">
<form>
<Heading>Sign In</Heading>
<Input
autoFocus
type="text"
className={formErrors.username.length>0? 'error': null}
name="username"
noValidate
placeholder="username"
onChange={this.handleChange}/>
{formErrors.username.length>0 && (
<span className="errorMessage">{formErrors.username}</span>
)}
<Input
name="password"
placeholder="Password"
onChange={this.handleChange}
type="password"
className={formErrors.password .length>0 ? 'error': null}/>
{formErrors.password .length>0 && (
<span className="errorMessage">{formErrors.password}</span>
)}
<div className="additional">
<FormGroup>
<FormCheck type="checkbox" value="remember" label="Remember me" />
</FormGroup>
<Link to ='/forgot-credentials'>Forgot credentials</Link>
</div>
<Button className="loginbtn" block bsSize="large" onClick={!isloading ? this.handleSubmit : null}>
{isloading ? 'Loading…' : 'Sign in'}
</Button>
**{wrongcredentials ? <div className="errorMessage">Wrong username or password</div> : null}**
</form>
<Footer>
<div className="company-login">
<p className="title-login">Pharmacy</p>
<h6 className="subtitle-login">Database Visualization</h6>
</div>
</Footer>
</div>
</div>
)
}
}
wrongcredentialsis not part of the component's state, React doesn't know that it has to re-render the component when its value changes. If you keep it in the state then the component will update.