useNavigate hook called inside useEffect causing infinite loop - javascript

i am using the useNavigate hook inside of react to direct users to a home page after successful login. everything i've read online suggests that i should use the useNavigate hook inside of a useEffect block, but when i do so, it triggers an infinite loop: Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
the odd thing is, though, that the warning only seems to occur after logging in for a second time. what i mean is that it will work on the first login after starting the server & client, but logging in a second, third, etc. time results in a Maximum update depth exceeded warning.
i use the useNavigate hook in two separate files, a login for users and a login for admin, both of which are below.
for further clarification on the issue arising only on the second login and beyond, it occurs regardless of whether i log in as admin or as a user. for instance, if my first login is as an admin, the Maximum update depth exceeded warning will occur regardless of whether my next login is as a user or as an admin. the same is true if my first login is as a user.
what i've tried so far:
removing navigate as from the dependency arrays (results in same warning)
removing the useEffect blocks (results in warnings to put the useNavigate hook inside of a useEffect hook. the login functionality breaks)
removing the dependency array altogether (results in the same warning)
the error when i login as user:
react-dom.development.js:86 Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
at Navigate (http://localhost:3000/static/js/bundle.js:42950:5)
at Routes (http://localhost:3000/static/js/bundle.js:43067:5)
at div
at Router (http://localhost:3000/static/js/bundle.js:43000:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:41809:5)
at App
the error when i login as admin:
react-dom.development.js:86 Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
at Navigate (http://localhost:3000/static/js/bundle.js:42950:5)
at Routes (http://localhost:3000/static/js/bundle.js:43067:5)
at div
at Router (http://localhost:3000/static/js/bundle.js:43000:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:41809:5)
at App
Login.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { Link, useNavigate} from "react-router-dom";
const Login = () => {
const navigate = useNavigate();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
useEffect(() => {
if (localStorage.getItem("authToken")) {
navigate("/home");
}
}, [navigate]);
const loginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post("/api/auth/login", { email, password }, config);
localStorage.setItem("authToken", data.token);
navigate("/home");
} catch (error) {
setError(error.response.data.error);
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="login-">
<form onSubmit={loginHandler} className="login-__form">
<h3 className="login-__title">Login</h3>
{error && <span className="error-message">{error}</span>}
<div className="form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
required
id="email"
placeholder="Email address"
onChange={(e) => setEmail(e.target.value)}
value={email}
tabIndex={1}
/>
</div>
<div className="form-group">
<label htmlFor="password">
Password:{" "}
{/* <Link to="/forgotpassword" className="login-__forgotpassword">
Forgot Password?
</Link> */}
</label>
<input
type="password"
required
id="password"
autoComplete="true"
placeholder="Enter password"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
</div>
<button type="submit" className="btn btn-primary">
Login
</button>
<span className="login-__subtext">
Don't have an account? <Link to="/register">Register</Link>
</span>
</form>
</div>
);
};
export default Login;
AdminLogin.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { Link, useNavigate} from "react-router-dom";
const AdminLogin = () => {
const navigate = useNavigate();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
useEffect(() => {
if (localStorage.getItem("adminToken")) {
navigate("/admin/home");
}
}, [navigate]);
const adminLoginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post("/api/admin/login", { username, password }, config);
localStorage.setItem("adminToken", data.token);
navigate("/admin/home");
} catch (error) {
setError(error.response.data.error);
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="login-">
<form onSubmit={adminLoginHandler} className="login-__form">
<h3 className="login-__title">admin login</h3>
{error && <span className="error-message">{error}</span>}
<div className="form-group">
<label htmlFor="username">Username:</label>
<input
type="username"
required
id="username"
placeholder="Username"
onChange={(e) => setUsername(e.target.value)}
value={username}
tabIndex={1}
/>
</div>
<div className="form-group">
<label htmlFor="password">
Password:{" "}
{/* <Link to="/forgotpassword" className="login-__forgotpassword">
Forgot Password?
</Link> */}
</label>
<input
type="password"
required
id="password"
autoComplete="true"
placeholder="Enter password"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
</div>
<button type="submit" className="btn btn-primary">
Login
</button>
<span className="login-__subtext">
Here by mistake? <Link to="/login">Login</Link>
</span>
</form>
</div>
);
};
export default AdminLogin;
it was asked in a comment, so i've also included Private.jsx (user home page) Admin.jsx (admin home page), though i don't think the issue is in either of these files.
Private.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
const Private = () => {
const [error, setError] = useState("");
const [privateData, setPrivateData] = useState("");
const navigate = useNavigate();
const handleLogout = () => {
localStorage.removeItem('authToken');
navigate('/login');
console.log('logged out successfully');
}
return error ? (
<span className="error-message">{error}</span>
) : (
<div>
you're in the private route
<button onClick = {handleLogout}>Logout</button>
</div>
);
};
export default Private;
Admin.jsx
import { useNavigate } from 'react-router-dom';
export default function Admin() {
const navigate = useNavigate();
const handleLogout = () => {
localStorage.removeItem('adminToken');
navigate('/admin/login');
console.log('logged out successfully');
}
return (
<>
<div>ADMIN ROUTE UNLOCKED</div>
<button onClick = {handleLogout}>Logout</button>
</>
)
}

You need to listen for changes in your localStorage. Try this:
const checkAuth = () => {
if (localStorage.getItem("authToken")) {
navigate("/home");
}
}
useEffect(() => {
window.addEventListener("storage", checkAuth);
return () => {
window.removeEventListener("storage", checkAuth)
}
}, []);

Related

React.js, How to fetch the properties in a URL pathname?

I'm trying to fetch the uid and token through the URL pathname using match in my React app. But I got error:
Uncaught TypeError: n is undefined
and this is my code snippet:
const ResetPasswordConfirm = ( {match, reset_password_confirm} ) => {
...
const onSubmit = e=> {
e.preventDefault();
const uid = match.params.uid;
const token = match.params.token;
reset_password_confirm(uid, token, new_password, re_new_password);
setRequestSent(true);
};
};
According to this thread: https://stackoverflow.com/questions/70609785/uncaught-typeerror-match-is-undefined#:~:text=react%2Drouter%2Ddom%20v5,render%20or%20children%20prop%20functions.
It says it might have something to do with the version of react router, so I tried to use useParams(), but I found it hard to implement it...
I also tried to use matchPath, but I can find few examples.
Can anybody help me with this issue please?
Update:
react-router-dom version: 6.8.0
ResetPasswordConfirm is running in my container package.
import React, { useState } from "react";
import { Navigate, useParams } from 'react-router-dom';
import { connect } from 'react-redux';
import { reset_password_confirm } from '../actions/auth';
const ResetPasswordConfirm = ( {match, reset_password_confirm} ) => {
const [requestSent, setRequestSent] = useState(false);
const [formData, setFormData] = useState({
new_password: '',
re_new_password: ''
});
const { new_password, re_new_password } = formData;
const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = e=> {
e.preventDefault();
const uid = match.params.uid;
const token = match.params.token;
reset_password_confirm(uid, token, new_password, re_new_password);
setRequestSent(true);
};
// Is the user sending the request?
// Redirect them to the home page
if (requestSent) {
return <Navigate to='/'/>
}
return (
<div className="container mt-5">
<form onSubmit={e => onSubmit(e)}>
{/* <div className="form-group">
<input className="form-control" type="email" placeholder="Email" name="email" value={email} onChange={e => onChange(e)} required></input>
</div>
<div className="form-group">
<input className="form-control" type="password" placeholder="Password" name="password" value={password} onChange={e => onChange(e)} minLength='6' required></input>
</div>
<button className="btn btn-primary" type="submit">Login</button> */}
<div className="form-group">
<label htmlFor="exampleInputPassword1">Password</label>
<input
type="password"
className="form-control"
id="exampleInputPassword1"
placeholder="New Password"
name="new_password"
value={new_password}
onChange={e => onChange(e)}
minLength='6'
required></input>
</div>
<div className="form-group">
<label htmlFor="exampleInputPassword1">Password</label>
<input
type="password"
className="form-control"
id="exampleInputPassword1"
placeholder="Confirm New Password"
name="re_new_password"
value={re_new_password}
onChange={e => onChange(e)}
minLength='6'
required></input>
</div>
<button type="submit" className="btn btn-primary">Reset Password</button>
</form>
</div>
);
};
export default connect(null, { reset_password_confirm }) (ResetPasswordConfirm);
Sorry for the lo-fi question. I will try to do better.
I tried to use useParams to fetch my uid
const onSubmit = e => {
...
let{uid} = useParams()
}
There are no longer route props in react-router-dom routed components, i.e. there is not any injected match prop. You'll use the useParams hook to access the route path params in RRDv6. You can't use React hooks in nested callbacks, they must be called in the function body of a React component or in custom React hooks. Use the useParams hook in the component body and destructure the uid and token path params. Since you are using hooks you may as well also import and use the useNavigate hook and issue the navigation action at the end of the form's onSubmit handler instead of enqueueing a state update.
import React, { useState } from "react";
import { useParams, useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { reset_password_confirm } from '../actions/auth';
const ResetPasswordConfirm = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const { uid, token } = useParams();
const [formData, setFormData] = useState({
new_password: '',
re_new_password: ''
});
const onChange = e => setFormData(formData => ({
...formData,
[e.target.name]: e.target.value
}));
const onSubmit = e => {
e.preventDefault();
const { new_password, re_new_password } = formData;
dispatch(reset_password_confirm(uid, token, new_password, re_new_password));
navigate("/");
};
return (
...
);
};
export default ResetPasswordConfirm;

auth.createUserWithEmailAndPassword is not a function, react

base.jsx:
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
config
};
export const app = initializeApp(firebaseConfig);
export const auth = getAuth();
Register.jsx
import React, { useState } from "react";
import { auth } from "../components/base";
import { Link, useNavigate } from "react-router-dom";
function Register() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState(null);
let navigate = useNavigate();
const handleRegister = async (e) => {
e.preventDefault();
try {
await auth.createUserWithEmailAndPassword(email, password);
await auth.signInWithEmailAndPassword(email, password);
navigate("/");
} catch (error) {
setError(error.message);
}
};
return (
<div className="register">
<div className="container">
<div className="box">
<form onSubmit={handleRegister}>
<h2>Register</h2>
<div className="form-group">
<label htmlFor="email">Email</label>
<input
type="email"
className="form-control"
id="email"
placeholder="Enter email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
id="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<button type="submit" className="btn btn-primary">
Register
</button>
<div>{error && <p className="error">{error}</p>}</div>
</form>
<p className="sign-up">
Already have an account?
<Link to="/login">
<span>Login</span>
</Link>
</p>
</div>
</div>
</div>
);
}
export default Register;
enter image description here
It's pretty much self explanatory, can you guys please help me fix this issue? I've been struggling for 2 hours.
I want createUserWithEmailAndPassword to work in Register.jsx so I can later on sign in Login.jsx with the same information. However on the website when I click the submit button in Register.jsx, auth.createUserWithEmailAndPassword is not a function pops out
You're using the v9 SDK version, which uses a modular API with top-level functions. So createUserWithEmailAndPassword is not longer a method on the auth object, but is now a top-level function that you have to import similar to what you do for getAuth and to which you then pass the auth object as its first parameter:
createUserWithEmailAndPassword(auth, "username", "password")
When you are programming this new API or getting errors otherwise, I recommend keeping the documentation handy. In this case you can see code similar to what you're trying and what I have above in the documentation on creating a user. Also have a look at the blog post introducing the modular SDK, and the upgrade guide.

xhr.js:220 POST http://localhost:3000/EShop/register 400 (Bad Request)

Trying to POST request to send data to database but it always shows 400 bad request.
The AuthReducer file is as follow. Data is not getting posted when done in Frontend but its properly working when tested in postman api.
export const Register = (username, email , password) => async(disptach) => {
try{
disptach({type:REGISTER_USER_REQUEST})
const config = {
Headers:{
'Content-Type':'application/json'
}
}
const { data } = await axios.post('/EShop/register', {username ,email , password} , config)
disptach({
type:REGISTER_USER_SUCCESS,
payload:data.user
})
}catch(error){
disptach({
type:REGISTER_USER_FAIL,
payload : error.response.data.message
})
}
}
The register form is as follow..
import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom"
import { useSelector, useDispatch } from "react-redux"
import Loader from "./loader";
import { Register } from "../actions/UserAction";
import "../css-files/Account.css"
export default function register() {
const [email, setemail] = useState('');
const [password, setpassword] = useState('');
const [username, setusername] = useState('');
const disptach = useDispatch();
const navigate = useNavigate();
const { isAuthenticated, error, loading } = useSelector(state => state.user)
useEffect(() => {
if (isAuthenticated) {
navigate('/account/login')
}
}, [disptach, isAuthenticated])
const SubmitRegisterHandler = (e) => {
e.preventDefault()
disptach(Register(username, email, password))
}
return (
<div id="Account_container">
{loading ?
<Loader />
:
<div id="wrapper">
<div id="Wrap_First">
<img src="https://res.cloudinary.com/dqxozrie1/image/upload/v1659935744/eshop/online-registration-sign-up_gfb2gs.webp" />
</div>
<div id="Wrap_Second">
<div id="login">
<h2>Create New Account</h2>
<form onSubmit={SubmitRegisterHandler}>
<input
required
type="text"
placeholder="Username"
value={username}
onChange={(e) => { setusername(e.target.value) }}
/>
<input
required
type="email"
placeholder="Email"
value={email}
onChange={(e) => { setemail(e.target.value) }}
/>
<input
required
type="password"
placeholder="Password"
value={password}
onChange={(e) => { setpassword(e.target.value) }}
/>
<button>Register</button>
</form>
<p id="existing_acc"><Link to="/account/login">Already have an account !</Link></p>
</div>
</div>
</div>
}
</div>
);
}
It gives 400 bad request always. Please help me how to resolve this issue.

Local storage token Problems

So this problem I am facing for quite some time. Basically Registering user work to some extent. This is what is happening, upon the user being created and me getting the Auth token displayed in the dev-tools/Application and me being pushed to the home as I should.
When I refresh the page I get this error × Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://reactjs.org/link/crossorigin-error for more information. I can fix this by clearing the localStorage. So if every time a new user is created, and if it wants to refresh the page, I will have to clear local storage every time. Which is totally not convenient.
There is another error, The logout handler is bugging, when I press the logout button it is displaying this error TypeError: Cannot read property 'push' of undefined and it pointing out the error is located in the UserContext. I would really appreciate some help really.
User Context
import React from "react";
import { useHistory } from "react-router-dom"
const UserContext = React.createContext();
function getUserFromLocalStorage() {
return localStorage.getItem("authToken")
? JSON.parse(localStorage.getItem("authToken"))
: { username: null, token: null };
}
function UserProvider({ children }) {
const [user, setUser] = React.useState(getUserFromLocalStorage());
const routerHistory = useHistory()
const logoutHandler = () =>{
localStorage.removeItem("authToken");
setUser(user);
routerHistory.push("/")
}
return (
<UserContext.Provider
value={{ user, setUser, logoutHandler }}
>
{children}
</UserContext.Provider>
);
}
export { UserContext, UserProvider };
Login
import React, { useState, } from "react";
import { useHistory } from "react-router-dom"
import axios from "axios";
import { Link } from "react-router-dom";
import "./Signin.css";
import { UserContext } from "../../context/user";
const Login = () => {
const { user, setUser } = React.useContext(UserContext);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const history = useHistory()
const loginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post(
"http://localhost:5000/api/auth/login",
{ email, password },
config
);
user.authToken = data.token;
setUser(user)
history.push("/");
} catch (error) {
if (error.response) {
setError(error.response.data.error);
}
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="signin">
<Link to='/'>
<img src='/audible/logo.png' />
</Link>
<form onSubmit={loginHandler} className="form__container">
<h3>Sign in with your Amazon account</h3>
{error && <span className="error__message">{error}</span>}
<span className='labels'>Email </span>
<input
className="input__field"
type="email"
required
id="email"
onChange={(e) => setEmail(e.target.value)}
value={email}
tabIndex={1}
/>
<span className='signin__forgot'>Password{" "}
<Link className='links' to="/forgotpassword" >
Forgot Password?
</Link>
</span>
<input
className="input__field"
type="password"
required
id="password"
autoComplete="true"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
<button type="submit" className="signin__btn">
Sign In
</button>
<span className='new__sign'>New to Amazon? </span>
<Link to="/register">
<button className='signin__register'>
Create your amazon account
</button>
</Link>
</form>
</div>
);
};
export default Login;
Register
import { useState, } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { useHistory } from "react-router-dom"
const Register = () => {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmpassword, setConfirmPassword] = useState("");
const [error, setError] = useState("");
const routerHistory = useHistory()
const registerHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
if (password !== confirmpassword) {
setPassword("");
setConfirmPassword("");
setTimeout(() => {
setError("");
}, 5000);
return setError("Passwords do not match");
}
try {
const { data } = await axios.post(
"http://localhost:5000/api/auth/register",
{
username,
email,
password,
},
config
);
localStorage.setItem("authToken", data.token);
routerHistory.push('/login')
} catch (error) {
if (error.response) {
setError(error.response.data.error);
}
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="signin">
<Link to='/'>
<img src='/audible/logo.png' />
</Link>
<form onSubmit={registerHandler} className="form__container">
<h3>Create account</h3>
{error && <span className="error__message">{error}</span>}
<span className='labels'>Username</span>
<input
type="text"
className="input__field"
required
id="name"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<span className='labels'>Email</span>
<input
type="email"
className="input__field"
required
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<span className='labels'>Password</span>
<input
type="password"
required
id="password"
className="input__field"
autoComplete="true"
placeholder="At least 6 characters"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<span className='labels'>Re-enter password</span>
<input
type="password"
required
id="confirmpassword"
className="input__field"
autoComplete="true"
value={confirmpassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
<button type="submit" className="register__btn">
Create your Amazon account
</button>
<span >
Already have an account? <Link className='links' to="/login">Login</Link>
</span>
</form>
</div>
);
};
export default Register;
Login Link
import React from "react";
import { Link, useHistory } from "react-router-dom";
import { CartContext } from "../../context/cart";
import { UserContext } from "../../context/user";
export default function LoginLink() {
const { user, logoutHandler } = React.useContext(UserContext);
const { clearCart } = React.useContext(CartContext);
if (user.authToken) {
return (
<button
onClick={() => {
logoutHandler();
clearCart()
}}
className="login-btn"
>
logout
</button>
);
}
return <Link to="/login">Signin</Link>;
}

Logout funcionality via local storage

So here I have Login funcionality via local storage token. I am getting the token upon user being created in The dev tools/Application it is redirecting me to the home that is working. The thing that is not working is this. Creating an user it is working but when it loads it should show logout instead of login, and should hide the cart Component. Where am I making a mistake
Context Api
import React from "react";
const UserContext = React.createContext();
function getUserFromLocalStorage() {
return localStorage.getItem("authToken")
? JSON.parse(localStorage.getItem("authToken"))
: { username: null, token: null };
}
function UserProvider({ children }) {
const [user, setUser] = React.useState(getUserFromLocalStorage());
const history = useHistory();
const logoutHandler = () =>{
localStorage.removeItem("user");
history.push("/")
}
return (
<UserContext.Provider
value={{ user, logoutHandler }}
>
{children}
</UserContext.Provider>
);
}
export { UserContext, UserProvider };
Login Link
import React from "react";
import { Link } from "react-router-dom";
import { UserContext } from "../../context/user";
import { useHistory } from "react-router-dom"
export default function LoginLink() {
const { user, logoutHandler } = React.useContext(UserContext);
if (user.authToken) {
return (
<button
onClick={() => {
logoutHandler();
}}
className="login-btn"
>
logout
</button>
);
}
return <Link to="/login">login</Link>;
}
Header
import React from 'react';
import { Link, useHistory } from "react-router-dom";
import Search from './Search';
import './Header.css'
import SearchBooks from './SearchBooks';
import LoginLink from '../Signin/LoginLink';
import CartLink from '../Cart/CartLink';
import { UserContext } from '../../context/user';
const Header = () => {
const { user } = React.useContext(UserContext);
return (
<div className='header__container'>
<Link to='/'>
<img src='/audi.png' />
</Link>
<li>
<LoginLink />
</li>
{user.authToken &&(
<CartLink />
)
}
</div>
)
}
export default Header
Login Component
import { useState, } from "react";
import { useHistory } from "react-router-dom"
import axios from "axios";
import { Link } from "react-router-dom";
import "./Signin.css";
const Login = () => {
const { user, setUser } = React.useContext(UserContext);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const history = useHistory()
const loginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post(
"http://localhost:5000/api/auth/login",
{ email, password },
config
);
localStorage.setItem("authToken", data.token);
setUser(user)
history.push("/");
} catch (error) {
if (error.response) {
setError(error.response.data.error);
}
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="login-screen">
<form onSubmit={loginHandler} className="login-screen__form">
<h3 className="login-screen__title">Login</h3>
{error && <span className="error-message">{error}</span>}
<div className="form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
required
id="email"
placeholder="Email address"
onChange={(e) => setEmail(e.target.value)}
value={email}
tabIndex={1}
/>
</div>
<div className="form-group">
<label htmlFor="password">
Password:{" "}
<Link to="/forgotpassword" className="login-screen__forgotpassword">
Forgot Password?
</Link>
</label>
<input
type="password"
required
id="password"
autoComplete="true"
placeholder="Enter password"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
</div>
<button type="submit" className="btn btn-primary">
Login
</button>
<span className="login-screen__subtext">
Don't have an account? <Link to="/register">Register</Link>
</span>
</form>
</div>
);
};
export default Login;
After you login, you have only set the authToken into your localStorage and not in your Provider. You'll need to call setUser after you login in order for Header component to know user is logged in.

Categories