'Component re run multiple times on setting state
I am trying to set my state in component did Mount lifecycle method in order to check the data I am getting from local storage and taking decision either to direct the user to the login page or keep remain the user on the dashboard if my local storage data exists in my local storage.
Or is there any way I can prevent switching the page to login on refreshing the web page and remain on the same even after reloading the browser if I have my data in local storage.
Thanks in advance!
import React, { Component } from "react";
import { Row, Col, Input, Button, Alert, Container, Label } from "reactstrap";
// Redux
import { connect } from "react-redux";
import { withRouter, Link, Route, Redirect } from "react-router-dom";
// availity-reactstrap-validation
import { AvForm, AvField } from "availity-reactstrap-validation";
// actions
import { checkLogin, apiError } from "../../store/actions";
import { loginAction } from "../../redux/actions/authActions";
// import images
import logodark from "../../assets/images/logo-dark.png";
import logolight from "../../assets/images/logo-light.png";
class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: "[email protected]",
password: "246810",
};
this.handleSubmit = this.handleSubmit.bind(this);
}
async handleSubmit(event, values) {
this.props.checkLogin(values, this.props.history);
const { username, password } = this.state;
localStorage.setItem("username", username);
localStorage.setItem("password", password);
let action = await this.props.loginAction(values, () => {
this.props.history.push({
pathname: "/dashboard",
});
});
}
// username = localStorage.getItem("username");
// password = localStorage.getItem("password");
// if (window.performance.getEntriesByType("navigation")[0].type).toSring() === 'back_forward') {
// window.location.reload()
// }
updateUser = (username, password) => {
this.setState({ username: username, password: password });
};
componentDidMount() {
// this.setState({
// // set username and password from local storage
// username: JSON.parse(localStorage.getItem("username")),
// password: JSON.parse(localStorage.getItem("password")),
// });
const username = localStorage.getItem("username");
const password = localStorage.getItem("password");
this.props.apiError("");
document.body.classList.add("auth-body-bg");
console.log("on page reload", window.performance.navigation);
if (window.performance.navigation.type !== 0) {
if (username && password) {
this.props.history.push({
pathname: "/dashboard",
});
} else {
this.props.history.push({
pathname: "/login",
});
}
}
}
componentWillUnmount() {
document.body.classList.remove("auth-body-bg");
}
render() {
return (
<React.Fragment>
<div>
<Container fluid className="p-0">
<Row className="g-0">
<Col lg={4}>
<div className="authentication-page-content p-4 d-flex align-items-center min-vh-100">
<div className="w-100">
<Row className="justify-content-center">
<Col lg={9}>
<div>
<div className="text-center">
<div>
<Link to="/" class="">
<img
src={logodark}
alt=""
height="20"
class="auth-logo logo-dark mx-auto"
/>
<img
src={logolight}
alt=""
height="20"
class="auth-logo logo-light mx-auto"
/>
</Link>
</div>
<h4 className="font-size-18 mt-4">
Welcome Back !
</h4>
{/* <p className="text-muted">Sign in to continue to Nazox.</p> */}
</div>
{/* {this.props.loginError && this.props.loginError ? <Alert color="danger">{this.props.loginError}</Alert> : null} */}
<div className="p-2 mt-5">
<AvForm
className="form-horizontal"
onValidSubmit={this.handleSubmit}
>
<div className="auth-form-group-custom mb-4">
<i className="ri-user-2-line auti-custom-input-icon"></i>
<Label htmlFor="username">Email</Label>
<AvField
name="username"
value={this.state.username}
type="text"
className="form-control"
id="username"
validate={{ email: true, required: true }}
placeholder="Enter username"
/>
</div>
<div className="auth-form-group-custom mb-4">
<i className="ri-lock-2-line auti-custom-input-icon"></i>
<Label htmlFor="userpassword">Password</Label>
<AvField
name="password"
value={this.state.password}
type="password"
className="form-control"
id="userpassword"
placeholder="Enter password"
/>
</div>
{/* <div className="form-check">
<Input type="checkbox" className="form-check-input" id="customControlInline" />
<Label className="form-check-label" htmlFor="customControlInline">Remember me</Label>
</div> */}
<div className="mt-4 text-center">
<Button
color="primary"
className="w-md waves-effect waves-light"
type="submit"
>
Log In
</Button>
</div>
{/* <div className="mt-4 text-center">
<Link to="/forgot-password" className="text-muted"><i className="mdi mdi-lock me-1"></i> Forgot your password?</Link>
</div> */}
</AvForm>
</div>
<div className="mt-5 text-center">
<p>
Don't have an account ?{" "}
<Link
to="/register"
className="fw-medium text-primary"
>
{" "}
Register{" "}
</Link>{" "}
</p>
{/* <p>© 2021 Nazox. Crafted with <i className="mdi mdi-heart text-danger"></i> by Themesdesign</p> */}
</div>
</div>
</Col>
</Row>
</div>
</div>
</Col>
<Col lg={8}>
<div className="authentication-bg">
<div className="bg-overlay"></div>
</div>
</Col>
</Row>
</Container>
</div>
</React.Fragment>
);
}
}
const mapStatetoProps = (state) => {
const { loginError } = state.Login;
return { loginError };
};
export default withRouter(
connect(mapStatetoProps, { checkLogin, apiError, loginAction })(Login)
);
Solution 1:[1]
You should consider to implement some Error Boundaries (if using React 16+);
If errors are not caught by any error boundary, this will result in unmounting of the whole component tree (https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html).
If the unmounting in turn changes something inside the store, this will cause re-rendering again in an infinite loop.
One error could occur (and probably not caught if you don't have Error Boundaries) beacuse you're using JSON.parse(localStorage.getItem("username")) in setState().
If the item inside localStorage is a normal string (as probably is), JSON.parse(<string>) will result in an error.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | cheesyMan |

