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'
Related
I am making a user context that has all of my user information that I need initially it is null and I update it in the login page but after I login and try to access the context from any other page it is still null
here is the code
CurrentUserContext.js
import { createContext } from "react";
export const CurrentUserContext = createContext(null);
UserContextLayout.jsx
import { Outlet } from "react-router-dom";
import { useState, useMemo, useCallback } from "react";
import { CurrentUserContext } from "../hooks/CurrentUserContext";
const UserContextLayout = () => {
const [currentUserContext, setCurrentUserContext] = useState(null);
return (
<CurrentUserContext.Provider
value={[currentUserContext, setCurrentUserContext]}
>
<Outlet />
</CurrentUserContext.Provider>
);
};
export default UserContextLayout;
MainRouter.jsx
import { Route, Routes } from "react-router-dom";
import Signin from "./pages/Signin";
import LandingPage from "./pages/LandingPage";
import { isAuthenticated } from "./apis/auth/auth-helper";
import UserContextLayout from "./utils/UserContextLayout";
const MainRouter = () => {
return (
<Routes>
<Route element={<UserContextLayout />}>
<Route path="/" element={<LandingPage />}></Route>
<Route
path="/signin"
element={
!isAuthenticated() ? <Signin /> : <Navigate to="/" replace={true} />
}
></Route>
</Route>
</Routes>
);
};
export default MainRouter;
Signin.jsx
import { useState, useContext } from "react";
import { GrTechnology } from "react-icons/gr";
import { CurrentUserContext } from "../hooks/CurrentUserContext";
import { signin } from "../apis/auth/auth-api";
import { authenticate } from "../apis/auth/auth-helper";
import { useNavigate } from "react-router-dom";
const Signin = () => {
const [currentUserContext, setCurrentUserContext] =
useContext(CurrentUserContext);
const navigate = useNavigate();
const [user1, setUser1] = useState({
email: "",
password: "",
});
const [rememberMe, setrememberMe] = useState(false);
const handleChange = (e) => {
setUser1((prev) => ({ ...prev, [e.target.name]: e.target.value }));
};
const handleRememberMeClick = () => {
setrememberMe((prev) => !prev);
};
const handleSubmit = async () => {
try {
const response = await signin(user1);
// if (res.status == 200) {
setCurrentUserContext(response.data.user);
authenticate(response.data.token, rememberMe);
navigate("/");
// } else {
// throw new Error("Authentication failed");
// }
} catch (error) {
console.log(error);
}
};
return (
<>
<div >
<div >
<h2 >
Sign in to your account
</h2>
<div >
<div>
<div>
<label htmlFor="email-address">
Email address
</label>
<input
id="email-address"
name="email"
type="email"
autoComplete="email"
required
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="password">
Password
</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
onChange={handleChange}
/>
</div>
</div>
<div >
<div >
<input
id="remember-me"
name="remember-me"
type="checkbox"
onClick={handleRememberMeClick}
/>
<label
htmlFor="remember-me"
>
Remember me
</label>
</div>
</div>
<div>
<button
type="submit"
onClick={handleSubmit}
>
Sign in
</button>
</div>
</div>
</div>
</div>
</>
);
};
export default Signin;
response.data.user has the user data that I want to save in the context but the context is not updated when I call setCurrentUserContext
I am trying to implement this feature in my React JS app where if I login successfully, the UI would display the Logout button in the navbar. But if I click on the Logout, I would be logged out from the main UI and redirected to the Login Page where the navbar won't have any Logout Button. Currently, when I log in to the main UI successfully, then I have to refresh the browser tab to show the logout button. It does not appear automatically once I log in successfully.
This is my header Component:
import React, { Component } from "react";
import { BrowserRouter as Router, Link } from "react-router-dom";
import AuthenticationService from "../Login/AuthenticationService";
class HeaderComponent extends Component {
render() {
const isUserLoggedIn = sessionStorage.getItem("authenticatedUser");
console.log(isUserLoggedIn);
return (
<nav className="navbar navbar-expand-lg ">
<Router>
<div className="container-fluid">
<a className="navbar-brand" href="#">
<span className="header-title">TODO APP</span>
</a>
<ul className="navbar-nav d-flex flex-row ms-auto me-3">
{isUserLoggedIn && (
<Link
to="/login"
onClick={() => {
window.location.href = "/login";
}}
>
{" "}
<button
className="btn btn-success logout-button"
onClick={AuthenticationService.logout}
>
Logout
</button>
</Link>
)}
</ul>
</div>
</Router>
{" "}
</nav>
);
}
}
export default HeaderComponent;
The isUserLoggedIn is a boolean value that is retrieved from the session storage. If isUserLoggedIn is true then the Logout button would be displayed on the Navbar.
const isUserLoggedIn = sessionStorage.getItem("authenticatedUser");
The AuthenticationService.js file is:
import React, { Component } from "react";
class AuthenticationService extends Component {
registerSuccessfulLogin(username, password) {
console.log("Login Successful");
sessionStorage.setItem("authenticatedUser", username);
console.log(sessionStorage.getItem("authenticatedUser"));
}
isUserLoggedIn() {
let user = sessionStorage.getItem("authenticatedUser");
if (user === null) {
return false;
} else {
return true;
}
// return true;
}
logout() {
sessionStorage.removeItem("authenticatedUser");
}
getLoggedInUserName() {
let user = sessionStorage.getItem("authenticatedUser");
if (user === null) return "";
return user;
}
}
export default new AuthenticationService();
The App.js component is:
import "./App.css";
import DropDownMenu from "./components/DropdownMenu/DropDownMenu";
import HeaderComponent from "./components/Header/HeaderComponent";
import LoginComponent from "./components/Login/LoginComponent";
import {
BrowserRouter as Router,
Routes,
Route,
useParams,
Link,
} from "react-router-dom";
import "./styles.css";
import "./loginStyle.css";
import "./Header.css";
import ErrorComponent from "./components/search-options/ErrorComponent";
import AuthenticatedRoute from "./components/DropdownMenu/AuthenticatedRoute";
function App() {
return (
<div className="App">
<HeaderComponent />
<Router>
<Routes>
<Route path="/" element={<LoginComponent />}></Route>
{/* <Route path="/login" element={<Navigate to="/LoginComponent" />} /> */}
<Route path="/login" default element={<LoginComponent />}></Route>
<Route
path="/pst"
element={
<AuthenticatedRoute>
<DropDownMenu />
</AuthenticatedRoute>
}
></Route>
<Route path="*" element={<ErrorComponent />}></Route>
</Routes>
</Router>
</div>
);
}
export default App;
I am not sure why do I have to refresh the Tab to show the Logout button on to the NavBar.
EDIT
I have added the Login component for further reference:
import axios from "axios";
import { data } from "jquery";
import React, { Component } from "react";
import { useNavigate } from "react-router";
import App from "../../App";
import HeaderComponent from "../Header/HeaderComponent";
import GetUserIp from "../tracking/GetUserIp";
import TrackLoginActivity from "../tracking/TrackLoginActivity";
import AuthenticationService from "./AuthenticationService";
class LoginComponent extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
ipAddress: "",
hasLoginFailed: false,
isUserLoggedIn: false,
};
this.handleCredentialChange = this.handleCredentialChange.bind(this);
this.submitLogin = this.submitLogin.bind(this);
}
handleCredentialChange(event) {
console.log(event.target.name);
this.setState({ [event.target.name]: event.target.value });
}
submitLogin(event) {
event.preventDefault();
var session_url =
"login check api url";
GetUserIp.retrieveIpAddress().then((response) => {
this.setState({ ipAddress: response.data.ip });
});
console.log(this.state.ipAddress);
axios
.post(
session_url,
{},
{
auth: {
username: this.state.username,
password: this.state.password,
},
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
}
)
.then((response) => {
console.log("Authenticated");
console.log(this.props);
AuthenticationService.registerSuccessfulLogin(
this.state.username,
this.state.password
);
this.props.navigate(`/pst`);
//track user login activity into the DB Entity, smart_tool_login_logs
TrackLoginActivity.trackSuccessfulLogin(
this.state.username,
this.state.ipAddress
);
})
.catch((error) => {
console.log("Error on autheication");
this.setState({ hasLoginFailed: true });
});
}
render() {
return (
<div className="login-app">
<form action="" className="login-form" onSubmit={this.submitLogin}>
<div className="container">
<input
type="text"
placeholder="username"
name="username"
className="username-value"
maxLength={30}
autoComplete="on"
value={this.state.username}
onChange={this.handleCredentialChange}
/>
<input
type="password"
placeholder="password"
name="password"
className="password-value"
maxLength={30}
autoComplete="on"
value={this.state.password}
onChange={this.handleCredentialChange}
/>
{this.state.hasLoginFailed && (
<div className="login-fail-message">
Invalid username/password
</div>
)}
<div className="login-btn"></div>
<button className="btn btn-success login-btn" type="submit">
Login
</button>
</div>
</form>
</div>
);
}
}
function WithNavigate(props) {
let navigate = useNavigate();
return <LoginComponent {...props} navigate={navigate} />;
}
export default WithNavigate;
Your header component is a stateless component, it has neither props nor internal state, so it is only rendered once with the initial value of isUserLoggedIn.
If you want the header component to react to the login status, it needs to be notified in some way that the value has changed. The easiest way to do so is to store this information in the state of your App component, then passing it down as a prop to the HeaderComponent.
// App.js
import "./App.css";
import DropDownMenu from "./components/DropdownMenu/DropDownMenu";
import HeaderComponent from "./components/Header/HeaderComponent";
import LoginComponent from "./components/Login/LoginComponent";
import {
BrowserRouter as Router,
Routes,
Route,
useParams,
Link,
} from "react-router-dom";
import "./styles.css";
import "./loginStyle.css";
import "./Header.css";
import ErrorComponent from "./components/search-options/ErrorComponent";
import AuthenticatedRoute from "./components/DropdownMenu/AuthenticatedRoute";
import AuthenticationService from "../Login/AuthenticationService";
function App() {
const [isUserLoggedIn, setIsUserLoggedIn] = useState(AuthenticationService.isUserLoggedIn()) // use the session storage to get the initial state's value
function onLoginSuccessful() {
setIsUserLoggedIn(true); // update the state to notify React the value has changed
}
return (
<div className="App">
<HeaderComponent isUserLoggedIn={isUserLoggedIn} /> {/* pass down the state value as a prop */}
<Router>
<Routes>
<Route path="/" element={<LoginComponent onLoginSuccessful={onLoginSuccessful}/>}></Route>
{/* <Route path="/login" element={<Navigate to="/LoginComponent" />} /> */}
<Route path="/login" default element={<LoginComponent onLoginSuccessful={onLoginSuccessful} />}></Route>
<Route
path="/pst"
element={
<AuthenticatedRoute>
<DropDownMenu />
</AuthenticatedRoute>
}
></Route>
<Route path="*" element={<ErrorComponent />}></Route>
</Routes>
</Router>
</div>
);
}
export default App;
// HeaderComponent.js
import React, { Component } from "react";
import { BrowserRouter as Router, Link } from "react-router-dom";
import AuthenticationService from "../Login/AuthenticationService";
class HeaderComponent extends Component {
render() {
const isUserLoggedIn = this.props.isUserLoggedIn; // retrieve the value from the props
console.log(isUserLoggedIn);
return (
<nav className="navbar navbar-expand-lg ">
<Router>
<div className="container-fluid">
<a className="navbar-brand" href="#">
<span className="header-title">TODO APP</span>
</a>
<ul className="navbar-nav d-flex flex-row ms-auto me-3">
{isUserLoggedIn && (
<Link
to="/login"
onClick={() => {
window.location.href = "/login";
}}
>
{" "}
<button
className="btn btn-success logout-button"
onClick={AuthenticationService.logout}
>
Logout
</button>
</Link>
)}
</ul>
</div>
</Router>
{" "}
</nav>
);
}
}
export default HeaderComponent;
Note that you also have to pass a callback to LoginComponent to be called once the user successfully logs in. Using state updates, React gets notified that the value of isUserLoggedIn has changed and will re-render the components that depend on this value, including HeaderComponent.
EDIT: I updated the implementation of LoginComponent with the callback I mentionned
// LoginComponent.js
import axios from "axios";
import { data } from "jquery";
import React, { Component } from "react";
import { useNavigate } from "react-router";
import App from "../../App";
import HeaderComponent from "../Header/HeaderComponent";
import GetUserIp from "../tracking/GetUserIp";
import TrackLoginActivity from "../tracking/TrackLoginActivity";
import AuthenticationService from "./AuthenticationService";
class LoginComponent extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
ipAddress: "",
hasLoginFailed: false,
isUserLoggedIn: false,
};
this.handleCredentialChange = this.handleCredentialChange.bind(this);
this.submitLogin = this.submitLogin.bind(this);
}
handleCredentialChange(event) {
console.log(event.target.name);
this.setState({ [event.target.name]: event.target.value });
}
submitLogin(event) {
event.preventDefault();
var session_url =
"login check api url";
GetUserIp.retrieveIpAddress().then((response) => {
this.setState({ ipAddress: response.data.ip });
});
console.log(this.state.ipAddress);
axios
.post(
session_url,
{},
{
auth: {
username: this.state.username,
password: this.state.password,
},
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
}
)
.then((response) => {
console.log("Authenticated");
console.log(this.props);
AuthenticationService.registerSuccessfulLogin(
this.state.username,
this.state.password
);
// add this line to your `LoginComponent` so that
// onLoginSuccessul is called when user is logged in
this.props.onLoginSuccessful();
this.props.navigate(`/pst`);
//track user login activity into the DB Entity, smart_tool_login_logs
TrackLoginActivity.trackSuccessfulLogin(
this.state.username,
this.state.ipAddress
);
})
.catch((error) => {
console.log("Error on autheication");
this.setState({ hasLoginFailed: true });
});
}
render() {
return (
<div className="login-app">
<form action="" className="login-form" onSubmit={this.submitLogin}>
<div className="container">
<input
type="text"
placeholder="username"
name="username"
className="username-value"
maxLength={30}
autoComplete="on"
value={this.state.username}
onChange={this.handleCredentialChange}
/>
<input
type="password"
placeholder="password"
name="password"
className="password-value"
maxLength={30}
autoComplete="on"
value={this.state.password}
onChange={this.handleCredentialChange}
/>
{this.state.hasLoginFailed && (
<div className="login-fail-message">
Invalid username/password
</div>
)}
<div className="login-btn"></div>
<button className="btn btn-success login-btn" type="submit">
Login
</button>
</div>
</form>
</div>
);
}
}
function WithNavigate(props) {
let navigate = useNavigate();
return <LoginComponent {...props} navigate={navigate} />;
}
export default WithNavigate;
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
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
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.