I'm rather new to React and Redux, and I have gotten a bit stuck when displaying the error state based on an error response from the server (using express).
Most of the other similar issues I've researched are related to onClick, onSubmit, or onChange, but I have not seen one like mine.
Expected result: The error state is retrieved from the store and displayed within the component
The issue stems from this segment:
if (nextProps.errors){
this.setState({ errors: nextProps.errors });
}
The full Login.js:
import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import "../css/login.css";
import { loginUser } from "../../redux/actions/authActions";
import TextFieldGroup from "../common/textFieldGroup";
class Login extends Component {
constructor() {
super();
this.state = {
username: '',
password: '',
errors: {}
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
componentDidMount() {
if (this.props.auth.isAuthenticated) {
this.props.history.push('/dashboard');
}
}
componentDidUpdate(nextProps) {
if (nextProps.auth.isAuthenticated) {
this.props.history.push('/dashboard');
}
if (nextProps.errors){
this.setState({ errors: nextProps.errors });
}
}
onSubmit(e) {
e.preventDefault();
const userData = {
username: this.state.username,
password: this.state.password
};
this.props.loginUser(userData);
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
render() {
const { errors } = this.state;
return (
<div className="login">
<div className="container">
<div className="row">
<div className="col-md-8 m-auto">
<h1 className="display-4 text-center">Log In</h1>
<p className="lead text-center">
</p>
<form onSubmit={this.onSubmit}>
<TextFieldGroup
placeholder="username"
name="username"
type="username"
value={this.state.username}
onChange={this.onChange}
error={errors.username}
isRequired
/>
<TextFieldGroup
placeholder="Password"
name="password"
type="password"
value={this.state.password}
onChange={this.onChange}
error={errors.password}
isRequired
/>
<input type="submit" className="btn btn-info btn-block mt-4" />
</form>
</div>
</div>
</div>
</div>
);
}
}
Login.propTypes = {
loginUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth,
errors: state.errors
});
export default connect(mapStateToProps, { loginUser })(Login);
I've tried:
- Assigning the value to a temp variable, but this is extremely clunky and makes the code confusing in my opinion.
- Validating if it is null/not null, naturally this reinforced the infinite loop or validated positively, as it was not null, so the error state never updates on the page.
I am definitely getting the correct error response from the server as I can see it in the Redux dev tools.
Thanks in advance.