So I have an issue where I set up the frontend so that when the user logs in, the Login button in the menu bar will change to display the user's name currently logged in with a drop-down list showing both the user profile and logout buttons. But every time I'm logging in with a user, the Login in the menu bar does not change, and even though in the console it says that the user has logged in, I can still go back to the login screen and log in again.
Below is the code:
Navbar
function Navbar() {
const [showLinks, setShowLinks] = useState(false);
const { state, dispatch: ctxDispatch } = useContext(Store);
const { cart, userInfo } = state;
const handleLogout = () => {
ctxDispatch({ type: 'USER_LOGOUT' });
localStorage.removeItem('userInfo');
};
console.log(userInfo);
<div className="rightSide">
<div className="linksTwo">
{/* {userInfo ? (
<NavDropdown id="nav-dropdown-light" title= {userInfo.name}>
<LinkContainer to="/profile">
<NavDropdown.Item> User Profile</NavDropdown.Item>
</LinkContainer>
<NavDropdown.Divider />
<Link
className="dropdown-item"
to="#logout"
onClick={handleLogout}
>
{' '}
Logout
</Link>
</NavDropdown>
) : ( */}
<Link to="/login">
Login <LoginIcon />
</Link>
{/* )} */}
</div>
</div>
Login
import Axios from 'axios';
import { useContext, useState } from 'react';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import Container from 'react-bootstrap/Container';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import { Helmet } from 'react-helmet-async';
import { Store } from '../components/Store';
import { toast } from 'react-toastify';
import { getError } from '../utils';
export default function Login() {
const navigate = useNavigate();
const { search } = useLocation();
const redirectInUrl = new URLSearchParams(search).get('redirect');
const redirect = redirectInUrl ? redirectInUrl : '/profile';
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { state, dispatch: ctxDispatch } = useContext(Store);
const { userInfo } = state;
function validateForm() {
return email.length > 0 && password.length > 0;
}
const handleSubmit = async (e) => {
e.preventDefault();
if (!password) {
toast.warn('Password is not correct');
return;
}
try {
const { data } = await Axios.post('/api/users/login', {
email,
password,
});
ctxDispatch({ type: 'USER_LOGIN', payload: data });
localStorage.setItem('userInfo', JSON.stringify(data));
navigate(redirect || '/profile');
toast.success(email + ' has logged in successfully');
} catch (err) {
toast.error(getError(err));
}
};
return (
<Container className="small-container">
<Helmet>
<title>Login</title>
</Helmet>
<h1 className="my-3">Login</h1>
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3" controlId="email">
<Form.Label>Email</Form.Label>
<Form.Control
type="email"
required
onChange={(e) => setEmail(e.target.value)}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="password">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
required
onChange={(e) => setPassword(e.target.value)}
autoComplete="on"
/>
</Form.Group>
<div className="m-3">
<Button
type="submit"
className="btn btn-outline-success me-2"
disabled={!validateForm()}
>
Login
</Button>
</div>
<div className="m-3">
New customer? <Link to={`/register`}>Register a new account</Link>
</div>
</Form>
</Container>
);
}
In Login component you are doing:
const { state, dispatch: ctxDispatch } = useContext(Store);
In Navbar Component you are doing:
const { state, userInfo, dispatch: ctxDispatch } = useContext(Store);
I guess that you are just destructuring your context bad in Navbar, try:
const { state, dispatch: ctxDispatch } = useContext(Store);
const { userInfo } = state;
Or you could also abbreviate it in : const { state: { userInfo }, dispatch: ctxDispatch } = useContext(Store);