I am trying to build a simple react login app that navigates to a home page after logging in using this.props.history.push(). Unfortunately, in all of my components this.props is undefined. Here are the relevant portions:
Root:
import React from 'react'
import {
BrowserRouter as Router,
Route
} from 'react-router-dom'
import Login from './views/Login'
import Index from './views/Index'
import Home from './views/Home'
const App = () => {
return(
<Router>
<div>
<Route exact path="/" component={Index}/>
<Route path="/login" component={Login}/>
<Route path="/home" component={Home}/>
</div>
</Router>
)
}
export default App
Index:
import React from 'react'
import Login from './Login'
import Home from './Home'
const Index = () => {
if (localStorage.getItem("username")) {
return(
<Home/>
);
} else {
return (
<Login/>
)
}
}
export default Index
Login:
import React from 'react'
const Login = () => {
let user, pass
const login = e => {
e.preventDefault();
fetch("http://localhost:3000/api/login", {
method: "GET",
headers: {
"user": user.value,
"pass": pass.value
}
})
.then(response => response.json())
.then(function(data) {
if (data.user) {
localStorage.setItem("username", data.user)
this.props.history.push("/");
} else {
console.log("Failed to get user")
}
})
}
return(
<div>
<h1>Login</h1>
<form onSubmit={login}>
<label> Username:
<input type="text" className="form-control col-md-12" ref = {node => user = node}/>
</label>
<label> Password:
<input type="password" className="form-control col-md-12" ref = {node => pass = node}/>
</label>
<br />
<input type="submit" value="Submit" />
</form>
</div>
)
}
export default Login
You also need withRouter from react-router-dom. Your login should look like this:
import React from 'react'
import { withRouter } from 'react-router-dom'
const Login = (props) => {
let user, pass
const login = e => {
e.preventDefault();
fetch("http://localhost:3000/api/login", {
method: "GET",
headers: {
"user": user.value,
"pass": pass.value
}
})
.then(response => response.json())
.then(function(data) {
if (data.user) {
localStorage.setItem("username", data.user)
props.history.push("/");
} else {
console.log("Failed to get user")
}
})
}
return(
<div>
<h1>Login</h1>
<form onSubmit={login}>
<label> Username:
<input type="text" className="form-control col-md-12" ref = {node => user = node}/>
</label>
<label> Password:
<input type="password" className="form-control col-md-12" ref = {node => pass = node}/>
</label>
<br />
<input type="submit" value="Submit" />
</form>
</div>
)
}
export default withRouter(Login)
withRouter is a higher order component. Higher order components are like wrappers that add additional functionality. They take a component as an argument and return a new component; in this case withRouter adds the history props.
Can read more about HOCs here: https://reactjs.org/docs/higher-order-components.html
Related
I believe the issue is the isAuthenticated state in the parent APP component is not being changed when bcrypt has confirmed credentials in the child Login component. I can't seem to get it to change.
I have added some console.log to see if change takes place and console.log 2 is skipped over and is never read.
The examples I keep finding pass a value back to parent when it the return() "html" portion of the child component function. I tried to use that as a basis for passing a call to the funciton in the parent to change the state. As I am here that method does not seem to work. Any guidance and/or explanation would be greatly appreciated.
The ideal situation would be after being authenticated by bcrypt, user would be redirected to private route /Post
APP:
import React, {useState} from 'react';
import './App.css';
import Nav from "./Nav";
import About from './About';
import Creater from './Creater';
import {BrowserRouter as Router, Switch, Route, Redirect, Link } from 'react-router-dom';
import { Layout} from './components/Layout';
import Home from "./Home";
import Post from "./Post";
import Login from './Login';
function App() {
const [isAuthenticated, setIsAuthenticated] = useState (false)
console.log(isAuthenticated + "1");
function auth () { setIsAuthenticated (true);
console.log(isAuthenticated + "2");
}
console.log(isAuthenticated + "3");
const PrivateRoute = ({ component: Component, ...rest}) => (
<Route {...rest} render={(props)=>(
isAuthenticated === true
? <Component {...props}/>
: <Redirect to='/login' />
)}/>
)
return (<Router>
<div className="App">
<Nav />
<Layout>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
<Route path="/creater" component={Creater} />
<Route auth={auth} path="/login" component={Login} />
<PrivateRoute isAuthenticated={isAuthenticated} path="/post" component={Post} />
</Switch>
</Layout>
</div>
</Router>
);
}
export default App;
Login:
import React, { useState } from "react";
import axios from 'axios';
var bcrypt = require('bcryptjs');
function Login({auth}) {
const [login, setLogin] = useState ({
adminname: "",
password: "",
});
function onChangeAdminname (event) {
setLogin({adminname: event.target.value,
password: login.password})
}
function onChangePassword (event) {
setLogin({adminname: login.adminname,
password: event.target.value})
}
function onSubmit ({event }) {
event.preventDefault();
const admin = login.adminname
const logpassword = login.password
axios.get('http://localhost:5000/admins', {
params: {
adminname: admin
}
})
.then(function (response) {
var pw = (response.data);
console.log(response.data);
bcrypt.compare(logpassword, pw[0].password, function(err, result){
if (result === true) {
console.log(auth);
auth();
window.location.pathname = "/post";
} else {
if(!alert("Admin name or password was incorrect, please try again")){window.location.reload();}
}
});
})
.catch(function (error) {
console.log(error);
});
}
return (
<div class="row">
<div class="col-sm-8">
<div class="card">
<div class="card-body">
<form
onSubmit={onSubmit}
>
<div class="form-group">
<input className="form-control"
type="text"
placeholder="Admin Name"
value={login.adminname}
onChange={onChangeAdminname}
name="adminmame"/>
</div>
<div class="form-group">
<input type="password"
className="form-control"
placeholder="Password"
value={login.password}
onChange={onChangePassword}
name="password"/>
</div>
<button value="POST" type="submit" className="btn btn-dark">Login</button>
</form>
</div>
</div>
</div>
</div>
)
}
export default Login;
post:
import React, { useState } from "react";
import axios from 'axios';
import {authenticated} from './Login';
import './App.css';
import DatePicker from 'react-datepicker';
import "react-datepicker/dist/react-datepicker.css";
function Post() {
const [postDate, setPostDate] = useState(new Date());
const [post, setPost] = useState({
title: "",
blog: "",
date: postDate,
});
function onChangeTitle(event) {
setPost({
title: event.target.value,
blog : post.blog,
date: post.date})
}
function onChangeBlog(event) {
setPost({
title: post.title,
blog : event.target.value,
date: post.date})
}
function onChangeDate(date) {
setPostDate(date);
}
function onSubmit(event) {
event.preventDefault();
axios.post('http://localhost:5000/posts/add', post)
.then(res => console.log(res.data));
window.location = '/';
}
return (
<div >
<h3>Compose a new post :D</h3>
<form onSubmit={onSubmit}>
<div className="form-group">
<input type="text"
required
className="form-control form-control-lg"
placeholder="Title"
value={post.title}
onChange={onChangeTitle}/>
</div>
<div>
<textarea type="text"
required
className="form-control form-control-lg"
rows="10"
placeholder="Tell a story"
value={post.blog}
onChange={onChangeBlog} ></textarea>
</div>
<div className="form-group">
<label>Date: </label>
<div>
<DatePicker
selected={postDate}
onChange={onChangeDate}/>
</div>
</div>
<div className="form-group">
<input type="submit" value="POST" className="btn btn-primary"/>
</div>
</form>
</div>
)
}
export default Post;
As far as I am concerned Bcrypt is not supported in ReactJS however can be used in NodeJS.
The browser supported version for Bcrypt is npm install bcryptjs
check their docs here:https://www.npmjs.com/package/bcryptjs
login undefined
I am getting login as undefined, whenever I click the login button it was working fine before I created AppRoutes.js and moved some of the routes into that file.
TypeError: login is not a function
here is the code structure.
this is the main file where app is started and login route is put here inside the AppRoutes component.
app.js
import React, { Fragment, useEffect } from 'react'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import Navbar from './components/layout/Navbar'
import Landing from './components/layout/Landing'
import Alert from './components/layout/Alert'
import { loadUser } from './actions/auth'
import { Provider } from 'react-redux'
import setAuthToken from './utils/setAuthToken'
import store from './store'
import './App.css'
import AppRoutes from './components/routing/AppRoutes'
if (localStorage.token) {
setAuthToken(localStorage.token)
}
const App = () => {
useEffect(() => {
store.dispatch(loadUser())
}, [])
return (
<Provider store={store}>
<Router >
<Fragment>
<Navbar />
<Alert />
<Switch>
<Route exact path='/' component={Landing} />
<Route component={AppRoutes} />
</Switch>
</Fragment>
</Router>
</Provider>
)
}
export default App
2.AppRoutes.js
import React, { Fragment } from 'react'
import { Register } from '../auth/Register'
import { Login } from '../auth/Login'
import Dashboard from '../dashboard/Dashboard'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import PrivateRoute from './PrivateRoute'
import { NotFound } from '../layout/NotFound'
import store from '../../store'
import { Provider } from 'react-redux'
const AppRoutes = () => {
return (<Fragment>
<Switch>
<Route exact path='/register' component={Register} />
<Route exact path='/login' component={Login} />
<PrivateRoute path='/dashboard' component={Dashboard} >
</PrivateRoute>
<Route component={NotFound} />
</Switch>
</Fragment>
)
}
export default AppRoutes
auth.js
export const login = (email, password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
}
const body = JSON.stringify({ email, password })
try {
const res = await axios.post('/api/auth', body, config)
if (res?.data?.token) {
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
})
dispatch(loadUser())
}
else {
dispatch(setAlert(res.data.msg, 'success'))
}
} catch (error) {
const errors = error.response.data.errors
if (errors) {
errors.forEach(error => dispatch(setAlert(error.msg, 'danger')))
}
dispatch({
type: LOGIN_FAIL
})
}
}
4.Login.js
import React, { Fragment, useState } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { login } from '../../actions/auth'
import { Link, Redirect } from 'react-router-dom'
import store from '../../store'
export const Login = ({ isAuthenticated, login }) => {
const [formData, setFormData] = useState({
email: '',
password: ''
})
const { email, password } = formData
const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value })
const onSubmit = e => {
e.preventDefault()
console.log(typeof login)
login(email, password)
}
//redirect if logged in
if (isAuthenticated) {
return <Redirect to='/dashboard' />
}
return (
<Fragment>
<div className="m-5">
<div className="row justify-content-center">
<div className="col-md-4">
<div className="card shadow-lg o-hidden border-0 my-5">
<div className="card-body p-0">
<div>
<div className="p-5">
<div className="text-center">
<h4 className="text-dark mb-4">Welcome Back!</h4>
</div>
<form className="user" onSubmit={e => onSubmit(e)}>
<div className="form-group">
<input className="form-control form-control-user" type="email" placeholder="Email Address" name="email" value={email} onChange={e => onChange(e)} required />
</div>
<div className="form-group">
<input className="form-control form-control-user" type="password"
placeholder="Password"
name="password"
minLength="6"
value={password} onChange={e => onChange(e)}
/>
</div>
<div className="form-group">
<div className="custom-control custom-checkbox small">
<div className="form-check">
<input className="form-check-input custom-control-input" type="checkbox" id="formCheck-1" />
<label className="form-check-label custom-control-label" htmlFor="formCheck-1">Remember Me</label>
</div>
</div>
</div><button className="btn btn-dark btn-block text-white btn-user" type="submit">Login</button>
<hr />
</form>
<div className="text-center"><Link to="/register" className="small" href="register.html">Create an Account!</Link></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</Fragment >
)
}
Login.propTypes = {
login: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool
}
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
})
export default connect(mapStateToProps, { login })(Login)
I am not able to figure out whether it is related to the route structure that i changed or is there a bigger problem that I am missing out on.
You have imported Login a named import in AppRoutes, whereas the connected component with Login was a default export which is why you see the issue
Change
import { Login } from '../auth/Login'
to
import Login from '../auth/Login'
i have a problem when i login using username and password. and when i submit. the page still not changes to /admin/index. but the path link already go to admin/index . for the example http://localhost:3000/ is the login page when i try to login the browser path become http://localhost:3000/admin/index but the page still not changes yet . and i must refresh the page first so the page will changes to dashboard
index.js
import React from "react";
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import { Router, Route, Switch} from "react-router-dom";
import { createBrowserHistory } from 'history';
import "assets/vendor/nucleo/css/nucleo.css";
import "assets/vendor/#fortawesome/fontawesome-free/css/all.min.css";
import "assets/scss/argon-dashboard-react.scss";
import AdminLayout from "layouts/Admin.js";
import reducer from './actions/reducer'
import LandingLogin from './layouts/LandingLogin.js'
import LandingRegister from './layouts/LandingRegister.js'
const store = createStore(reducer);
const customHistory = createBrowserHistory();
class App extends React.Component {
render () {
return (
<Provider store = {store}>
<Router history={customHistory}>
<Switch>
<Route path="/admin" render={props => <AdminLayout {...props} />} />
<Route path="/" render= {() => <LandingLogin/>} />
<Route exact path="/register" render= {() => <LandingRegister/>} />
</Switch>
</Router>
</Provider>
)
}
}
export default App;
login.js
import React, { Fragment } from 'react'
import { connect } from 'react-redux'
import axios from 'axios';
import { createBrowserHistory } from 'history';
import { Link } from 'react-router-dom'
// reactstrap components
import {
Button,
Card,
CardBody,
FormGroup,
Form,
Input,
InputGroupAddon,
InputGroupText,
InputGroup,
Col
} from "reactstrap";
const customHistory = createBrowserHistory();
class Login extends React.Component {
constructor(props) {
super(props);
const token = localStorage.getItem("token");
let isLogedIn = true
if (token === null) {
isLogedIn = false
}
this.state = {
post : [],
isLogedIn,
id : '',
email : '',
password: '',
}
this.handleForm = this.handleForm.bind(this);
this.submitLogin = this.submitLogin.bind(this);
}
getPostAPI = () => {
axios.get('http://localhost:8001/datauser')
.then((res) => {
this.setState ({
post : res.data
})
})
}
getPostAPI2 = () => {
axios.get('http://localhost:8001/dataadmin')
.then((res) => {
this.setState ({
post : res.data
})
})
}
handleForm = (e) => {
this.setState ({
[e.target.name] : e.target.value
})
}
submitLogin = (event) => {
event.preventDefault();
const { post, email, password } = this.state;
if(post.find(event => `${event.email}${event.password}` === `${email}${password}` )) {
localStorage.setItem("token","123456781234")
localStorage.setItem("username",email);
localStorage.setItem("password",password);
this.setState ({
isLogedIn : true
})
} else {
alert("Email atau Password Salah!");
this.setState ({
email : '',
password: ''
})
}
}
componentDidMount () {
this.getPostAPI2();
}
render() {
const { email, password } = this.state
if (this.state.isLogedIn) {
customHistory.push('/admin/index');
}
return (
<Fragment>
<Col lg="5" md="7">
<Card className="bg-secondary shadow border-0">
<CardBody className="px-lg-5 py-lg-5">
<div className="text-center text-muted mb-4">
<h2>Form Login</h2>
</div>
<Form role="form" onSubmit = {this.submitLogin}>
<FormGroup className="mb-3">
<InputGroup className="input-group-alternative">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="ni ni-email-83" />
</InputGroupText>
</InputGroupAddon>
<Input onChange={this.handleForm} value={email} name = "email" placeholder="Email" type="email" required />
</InputGroup>
</FormGroup>
<FormGroup>
<InputGroup className="input-group-alternative">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="ni ni-lock-circle-open" />
</InputGroupText>
</InputGroupAddon>
<Input onChange={this.handleForm} value={password} name = "password" placeholder="Password" type="password" required/>
</InputGroup>
</FormGroup>
<div className="custom-control custom-control-alternative custom-checkbox">
<input
className="custom-control-input"
id=" customCheckLogin"
type="checkbox"
/>
<label
className="custom-control-label"
htmlFor=" customCheckLogin"
>
<span className="text-muted">Remember me</span>
</label>
</div>
<div className="text-center">
<Button className="my-4" color="primary" type="submit">
Log in
</Button>
</div>
</Form>
</CardBody>
</Card>
</Col>
</Fragment>
);
}
}
function select(state) {
return {
users: state.users
}
}
export default connect(select)(Login);
i expect when login, the page directly change to dashboard without refresh the page. please tell me something what should i do
I am aiming to display the component "SignIn" when I select the sign in button in the landing page. However, the component in the landing page is still displayed after selecting the button. Here are some images illustrating this problem.
Before Click: enter image description here
After Click: enter image description here
The issue is the second image. What could be the biggest cause of it?
Input is greatly appreciated.
Code - Home Page (LandingPage):
import React from 'react';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import { Link } from 'react-router-dom';
import * as ROUTES from '../../routes.jsx';
import './LandingPage.css'
export default class LandingPage extends React.Component {
render() {
return(
<div>
<Button className="signInButton" variant="light"><Link to={ROUTES.SIGN_IN}>Sign In</Link></Button>
<h1 className="landingBanner" >Streamosphere</h1>
<SignUpFormBase/>
</div>
);
}
}
const INITIAL_STATE = {
email: '',
password: '',
error: null,
};
export default class SignUpFormBase extends React.Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
}
onSubmit = event => {
console.log("Props");
console.log(this.props);
const { history } = this.props;
const { email, password } = this.state;
this.props.firebase
.doCreateUserWithEmailAndPassword(email, password)
.then(authUser => {
this.setState({ ...INITIAL_STATE });
})
.catch(error => {
this.setState({ error });
});
event.preventDefault();
};
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const {
email,
password,
error,
} = this.state;
const isInvalid = password === '' || email === '';
return (
<Form className="signUpForm"
onSubmit={this.onSubmit}>
<h1 className="signUpBanner">Sign Up </h1>
<Form.Group controlId="formSignUpEmail">
<Form.Label>Email address</Form.Label>
<Form.Control name="email"
value={email}
onChange={this.onChange}
type="email"
placeholder="Enter email" />
<Form.Text className="text-muted">
We'll never share your email with anyone else.
</Form.Text>
</Form.Group>
<Form.Group controlId="formSignUpPassword">
<Form.Label>Password</Form.Label>
<Form.Control name="password"
value={password}
onChange={this.onChange}
type="password"
placeholder="Password" />
</Form.Group>
<Button type="submit"
disabled={isInvalid}
className="signUpButton"
variant="light" >
Sign Up
</Button>
{error && <p>{error.message}</p>}
</Form>
);
}
}
const SignUpLink = () => (
<p>
Already have an account? <Link to={ROUTES.SIGN_IN}>Sign In</Link>
</p>
);
Sign In (file w/ SignIn Component):
import React, { Component } from 'react';
import SignUpLink from './LandingPage.jsx'
import * as ROUTES from '../../routes.jsx';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import './LandingPage.css'
export default class SignInPage extends Component {
render() {
return(
<div>
<h1 className="landingBanner" >Streamosphere</h1>
<SignInFormBase/>
<SignUpLink />
</div>
);
}
}
const INITIAL_STATE = {
email: '',
password: '',
error: null,
};
export default class SignInFormBase extends Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
}
onSubmit = event => {
const { email, password } = this.state;
this.props.firebase
.doSignInWithEmailAndPassword(email, password)
.then(() => {
this.setState({ ...INITIAL_STATE });
this.props.history.push(ROUTES.HOME);
})
.catch(error => {
this.setState({ error });
});
event.preventDefault();
};
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const { email, password, error } = this.state;
const isInvalid = password === '' || email === '';
return (
<Form className="signUpForm"
onSubmit={this.onSubmit}>
<h1 className="signUpBanner"> Sign In </h1>
<Form.Group controlId="formSignInEmail">
<Form.Label>Email address</Form.Label>
<Form.Control name="email"
value={email}
onChange={this.onChange}
type="email"
placeholder="Enter email" />
<Form.Text className="text-muted">
We'll never share your email with anyone else.
</Form.Text>
</Form.Group>
<Form.Group controlId="formSignInPassword">
<Form.Label>Password</Form.Label>
<Form.Control name="password"
value={password}
onChange={this.onChange}
type="password"
placeholder="Password" />
</Form.Group>
<Button type="submit"
disabled={isInvalid}
className="signUpButton"
variant="light" >
Sign In
</Button>
{error && <p>{error.message}</p>}
</Form>
);
}
}
URL Routes (routes.jsx):
export const LANDING = '/';
export const SIGN_IN = '/signin';
export const HOME = '/home';
export const ACCOUNT = '/account';
App.jsx (entry point, where LandingPage is the 1st page rendered):
import { Route } from 'react-router'
import React from 'react';
import LandingPage from './components/containers/LandingPage'
import SignInPage from './components/containers/SignIn'
import HomePage from './components/containers/HomePage'
import * as ROUTES from './routes.jsx';
class App extends React.Component {
render() {
return (
<div>
<Route exact path={ROUTES.LANDING} component={LandingPage} />
<Route path={ROUTES.HOME} component={HomePage} />
<Route path={ROUTES.SIGN_IN} component={SignInPage} />
</div>
);
}
}
export default App;
It is because of the Link from react-router-dom.
You could circumvent it by reloading the whole page.
For example, use <a href="/sign-in></a> instead.
You need to wrap all routes in App with Switch which would render only one matching child component.
// App.jsx
import { Route, Switch } from 'react-router'
import React from 'react';
import LandingPage from './components/containers/LandingPage'
import SignInPage from './components/containers/SignIn'
import HomePage from './components/containers/HomePage'
import * as ROUTES from './routes.jsx';
class App extends React.Component {
render() {
return (
<Switch>
<Route exact path={ROUTES.LANDING} component={LandingPage} />
<Route path={ROUTES.HOME} component={HomePage} />
<Route path={ROUTES.SIGN_IN} component={SignInPage} />
</Switch>
);
}
}
export default App;
This question seems like duplicate but it's not. I understand the error and have solved such error number of time but this time I couldn't figure out what's causing infinite loop.
here is code for react component causing the error:
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import './Login.scss';
import axios from 'axios';
import { endPoint } from '../App/path';
import { logIn, isLoggedIn } from '../App/TokenStore';
const re = /^[a-zA-Z0-9_-]{3,15}$/;
class Login extends Component {
constructor() {
super();
this.state = {
username: '',
password: '',
errorMessage: 'Please Login to proceed!',
};
}
onUserNameChange = (e) => {
this.setState({ username: e.target.value });
}
onPasswordChange = (e) => {
this.setState({ password: e.target.value });
}
onFormSubmit = (event) => {
event.preventDefault();
const { username, password } = this.state;
const { history } = this.props;
const isUserNameValid = re.test(String(username).toLowerCase());
if (isUserNameValid) {
axios.post(`${endPoint}/login.json`, { username, password })
.then((response) => {
if (response.status === 200) {
if (response.statusText === 'OK') {
this.setState({
username: '', password: '', errorMessage: '',
});
if (response.config.data) {
console.log(response);
logIn(response.config.data, 'response.config.data.password');
history.push('/dashboard');
} else {
throw new Error();
}
} else {
this.setState({ errorMessage: 'Please enter valid credential!' });
}
}
}).catch((err) => {
if (err.response) {
this.setState({ errorMessage: 'Please enter valid username!' });
} else {
this.setState({ errorMessage: 'Unknown Error!!' });
}
});
} else {
this.setState({ errorMessage: 'Please enter valid username!' });
}
}
render() {
if (isLoggedIn()) {
return <Redirect to="/dashboard" />;
}
const {
username, password, errorMessage,
} = this.state;
return (
<div className="Login">
<form className="Form" onSubmit={this.onFormSubmit}>
<p className="errorMessage">{errorMessage}</p>
<div className="form__group">
<label id="username" className="Label" htmlFor="username">
<i className="fa fa-user" />
<b>Username</b>
</label>
<input
value={username}
onChange={e => this.onUserNameChange(e)}
id="username"
type="username"
placeholder="Your username"
required
/>
</div>
<div className="form__group">
<label id="password" className="Label" htmlFor="password">
<i className="fa fa-key" />
<b>Password</b>
</label>
<input
value={password}
onChange={e => this.onPasswordChange(e)}
id="password"
type="password"
placeholder="Your Password"
required
/>
</div>
<button type="submit" className="Btn">LOGIN</button>
</form>
</div>
);
}
}
Login.propTypes = {
history: PropTypes.shape(),
};
Login.defaultProps = { history: {} };
export default Login;
these are the other function I am using in the above component:
export const logIn = (username, token) => {
sessionStorage.setItem('username', username);
sessionStorage.setItem('loggedIn', true);
sessionStorage.setItem('token', token);
};
export const isLoggedIn = () => Boolean(sessionStorage.getItem('loggedIn'));
here is dashboard component
import React from 'react';
import { NavLink } from 'react-router-dom';
import './Dashboard.scss';
const dashboard = () => (
<div className="container">
<div className="row">
<div className="card col-5 mr-auto ml-auto">
<h5 className="card-header">Lorem ipsum</h5>
<div className="card-body">
<h5 className="card-title">Lorem ipsum</h5>
<p className="card-text">Lorem ipsum</p>
<NavLink to="/dashboard/VRlist" className="btn btn-dashboard">Update/Delete</NavLink>
</div>
</div>
<div className="card col-5 mr-auto ml-auto">
<h5 className="card-header">Lorem ipsum</h5>
<div className="card-body">
<h5 className="card-title">Lorem ipsum</h5>
<p className="card-text">Lorem ipsum</p>
<NavLink to="/dashboard/registration" className="btn btn-dashboard"> Registration</NavLink>
</div>
</div>
</div>
</div>
);
export default dashboard;
here is my main app component
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Navbar from './Navbar/Navbar';
import Login from './Login/Login';
import Dashboard from './Dashboard/Dashboard';
import { isLoggedIn } from './App/TokenStore';
import VRlist from './VRlist/VRlist';
import NewRegistration from './newRegistration/newRegistration';
import UpdateRegistration from './updateRegistration/updateRegistration';
const App = () => {
if (!isLoggedIn()) {
return (
<div>
<Navbar />
<Route component={Login} />
</div>
);
}
return (
<div>
<Navbar />
<Switch>
<Route exact path="/" component={Login} />
<Route path="/dashboard/VRlist/edit/:id" component={UpdateRegistration} />
<Route path="/dashboard/VRlist" component={VRlist} />
<Route path="/dashboard/registration" component={NewRegistration} />
<Route path="/dashboard" component={Dashboard} />
<Route component={Login} />
</Switch>
</div>
);
};
export default App;
Now when I run the application and do login, this error will happen only for the first time login in the current tab, if I refresh the page the error will go away.
Apparently, I've used react-router and react-router-dom version 5, that's what was causing an infinite render loop while calling an history.push(), however for the rest of the components 'history.push()' was working fine but login page. Though switching over to version 4.3.1 emitted issue completely.