为什么登录成功后菜单栏中显示的不是用户名而是登录图标?
Why is the name of the user is not being shown instead of the Login icon in the menu bar after a successful login?
所以我在设置前端时遇到了一个问题,当用户登录时,菜单栏中的“登录”按钮将更改为显示当前登录的用户名,下拉列表显示用户配置文件和注销按钮。但是每次我用用户登录时,菜单栏中的登录名不会改变,即使在控制台中显示用户已登录,我仍然可以返回登录屏幕并再次登录.
代码如下:
导航栏
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>
登录
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>
);
}
您在登录组件中执行的操作:
const { state, dispatch: ctxDispatch } = useContext(Store);
您在 Navbar 组件中正在做的事情:
const { state, userInfo, dispatch: ctxDispatch } = useContext(Store);
我猜测你只是在破坏导航栏中的上下文,试试:
const { state, dispatch: ctxDispatch } = useContext(Store);
const { userInfo } = state;
或者您也可以缩写为:
const { state: { userInfo }, dispatch: ctxDispatch } = useContext(Store);
所以我在设置前端时遇到了一个问题,当用户登录时,菜单栏中的“登录”按钮将更改为显示当前登录的用户名,下拉列表显示用户配置文件和注销按钮。但是每次我用用户登录时,菜单栏中的登录名不会改变,即使在控制台中显示用户已登录,我仍然可以返回登录屏幕并再次登录.
代码如下:
导航栏
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>
登录
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>
);
}
您在登录组件中执行的操作:
const { state, dispatch: ctxDispatch } = useContext(Store);
您在 Navbar 组件中正在做的事情:
const { state, userInfo, dispatch: ctxDispatch } = useContext(Store);
我猜测你只是在破坏导航栏中的上下文,试试:
const { state, dispatch: ctxDispatch } = useContext(Store);
const { userInfo } = state;
或者您也可以缩写为:const { state: { userInfo }, dispatch: ctxDispatch } = useContext(Store);