[英]React MongoDB E-Commerce website. If user is already logged in, how to redirect from "Account" button to User info instead of Login page?
我正在使用 React 和 MongoDB 創建一個電子商務網站。到目前為止,我有一個 JSON,它插入了一個產品列表,有人可以 select 並將其添加到購物車中進行購買。 設計方面即將完成,現在我正在處理功能方面的工作。
每個屏幕上出現的導航欄都有一個“帳戶”按鈕選項,可以將某人重定向到登錄頁面。 他們要么注冊一個帳戶,要么如果他們已經有一個帳戶,那么他們會在那里輸入信息並登錄,然后被重定向到“Home2”帳戶信息頁面。
我面臨的問題是,如果他們已經登錄並單擊導航欄中的“帳戶”按鈕,那么他們將被重定向回登錄頁面。 我想設置它,如果他們在登錄后單擊導航欄中的“帳戶”按鈕,那么他們將被重定向到“Home2”帳戶信息頁面。 我想這是某種類型的 if else 語句?
Index.JS 頁面
import React from 'react';
import ReactDOM from 'react-dom/client';
import '../node_modules/font-awesome/css/font-awesome.min.css';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './redux/store';
import Signup from "./pages/Signup.page";
import { UserProvider } from "./contexts/user.context";
import PrivateRoute from "./pages/PrivateRoute.page";
import Home2 from "./pages/Home2";
import { Home, Product, Products, AboutPage, ContactPage, Cart, Login, Register, Checkout, PageNotFound } from "./pages"
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
{/* We are wrapping our whole app with UserProvider so that */}
{/* our user is accessible through out the app from any page*/}
<UserProvider>
<Provider store={store}>
<UserProvider>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/product" element={<Products />} />
<Route path="/product/:id" element={<Product />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
<Route path="/cart" element={<Cart />} />
<Route exact path="/login" element={<Login />} />
<Route exact path="/signup" element={<Signup />} />
{/* We are protecting our Home Page from unauthenticated */}
{/* users by wrapping it with PrivateRoute here. */}
<Route element={<PrivateRoute />}>
<Route exact path="/Home2" element={<Home2 />} />
</Route>
<Route path="/register" element={<Register />} />
<Route path="/checkout" element={<Checkout />} />
<Route path="*" element={<PageNotFound />} />
<Route path="/product/*" element={<PageNotFound />} />
</Routes>
</UserProvider>
</Provider>
</UserProvider>
</BrowserRouter>
);
賬號按鈕所在的Navbar.Jsx頁面
import React from 'react'
import { NavLink } from 'react-router-dom'
import { useSelector } from 'react-redux'
const Navbar = () => {
const state = useSelector(state => state.handleCart)
return (
// Navbar
<nav className="navbar navbar-expand-lg navbar-light bg-light py-2 sticky-top">
<div className="container">
{/* Company Name/Logo */}
<NavLink className="navbar-brand fw-bold fs-4 px-2" to="/" ><img
className="card-img"
src="./assets/Logo2.jpg"
alt="Card"
height={100}/>
</NavLink>
{/* Nav Collapse */}
<button className="navbar-toggler mx-2" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
{/* Navigation Options */}
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav m-auto my-2 text-center">
<li>
<button className="nav-item graphic2 btn-8 m-2" >
<NavLink className="nav-link" to="/">Home </NavLink>
</button>
</li>
<li>
<button className="nav-item graphic2 btn-8 m-2" >
<NavLink className="nav-link" to="/product">Products</NavLink>
</button>
</li>
<li>
<button className="nav-item graphic2 btn-8 m-2" >
<NavLink className="nav-link" to="/about">About</NavLink>
</button>
</li>
<li >
<button className="nav-item graphic2 btn-8 m-2" >
<NavLink className="nav-link light" to="/contact">Contact</NavLink>
</button>
</li>
</ul>
{/* Account Info */}
<div className="buttons text-center">
<NavLink to="/login" className="btn btn-outline-dark m-2 graphic2 btn-8"style={{color: 'black', padding:'0.3rem'}}><i className="fa fa-user-plus mr-1"></i> Account</NavLink>
{/* <NavLink to="/register" className="btn btn-outline-dark m-2"><i className="fa fa-user-plus mr-1"></i> Register</NavLink> */}
<NavLink to="/cart" className="btn btn-outline-dark m-2 graphic2 btn-8"style={{color: 'black', padding:'0.3rem'}}><i className="fa fa-cart-shopping mr-1"></i> Cart ({state.length}) </NavLink>
</div>
</div>
</div>
</nav>
)
}
export default Navbar
登錄頁面
import { Button, TextField } from "@mui/material";
import { useContext, useEffect, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { UserContext } from "../contexts/user.context";
import { Navbar, Footer } from "../components";
import Card from '@mui/material/Card';
const Login = () => {
const navigate = useNavigate();
const location = useLocation();
// We are consuming our user-management context to
// get & set the user details here
const { user, fetchUser, emailPasswordLogin } = useContext(UserContext);
// We are using React's "useState" hook to keep track
// of the form values.
const [form, setForm] = useState({
email: "",
password: ""
});
// This function will be called whenever the user edits the form.
const onFormInputChange = (event) => {
const { name, value } = event.target;
setForm({ ...form, [name]: value });
};
// This function will redirect the user to the
// appropriate page once the authentication is done.
const redirectNow = () => {
const redirectTo = location.search.replace("?redirectTo=", "");
navigate(redirectTo ? redirectTo : "/Home2");
}
// Once a user logs in to our app, we don’t want to ask them for their
// credentials again every time the user refreshes or revisits our app,
// so we are checking if the user is already logged in and
// if so we are redirecting the user to the home page.
// Otherwise we will do nothing and let the user to login.
const loadUser = async () => {
if (!user) {
const fetchedUser = await fetchUser();
if (fetchedUser) {
// Redirecting them once fetched.
redirectNow();
}
}
}
// This useEffect will run only once when the component is mounted.
// Hence this is helping us in verifying whether the user is already logged in
// or not.
useEffect(() => {
loadUser(); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// This function gets fired when the user clicks on the "Login" button.
const onSubmit = async (event) => {
try {
// Here we are passing user details to our emailPasswordLogin
// function that we imported from our realm/authentication.js
// to validate the user credentials and log in the user into our App.
const user = await emailPasswordLogin(form.email, form.password);
if (user) {
redirectNow();
}
} catch (error) {
if (error.statusCode === 401) {
alert("Invalid username/password. Try again!");
} else {
alert(error);
}
}
};
return <>
<Navbar />
<Card sx={{ maxWidth: 600 }} style={{display: 'block', margin: 'auto', marginBottom: '5rem', marginTop: '5rem' }}>
<form style={{ display: "flex", flexDirection: "column", maxWidth: "300px", margin: "auto", marginTop: '3rem', marginBottom: '3rem' }}>
<h3 className="text-center">Login Page</h3>
<TextField
label="Email"
type="email"
variant="outlined"
name="email"
value={form.email}
onChange={onFormInputChange}
style={{ marginBottom: "1rem" }}
/>
<TextField
label="Password"
type="password"
variant="outlined"
name="password"
value={form.password}
onChange={onFormInputChange}
style={{ marginBottom: "1rem" }}
/>
<Button className="graphic2 btn-8 m-2" onClick={onSubmit}>
Login
</Button>
<p>Don't have an account? <Link to="/signup">Signup</Link></p>
</form>
</Card>
<Footer />
</>
}
export default Login;
主頁2
import { Button, CardActionArea } from '@mui/material'
import { useContext } from 'react';
import { UserContext } from '../contexts/user.context';
import { Footer, Navbar } from "../components";
import Card from '@mui/material/Card';
import Typography from '@mui/material/Typography';
import CardContent from '@mui/material/CardContent';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import BadgeIcon from '@mui/icons-material/Badge';
import EmailIcon from '@mui/icons-material/Email';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
export default function Home2() {
const { logOutUser } = useContext(UserContext);
// This function is called when the user clicks the "Logout" button.
const logOut = async () => {
try {
// Calling the logOutUser function from the user context.
const loggedOut = await logOutUser();
// Now we will refresh the page, and the user will be logged out and
// redirected to the login page because of the <PrivateRoute /> component.
if (loggedOut) {
window.location.reload(true);
}
} catch (error) {
alert(error)
}
}
return (
<>
<Navbar />
<h1 className="text-center mt-5 improv m-3" >Welcome back Name</h1>
<Card sx={{ maxWidth: 600 }} style={{display: 'block', margin: 'auto', marginBottom: '3rem' }}>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
Account Information
</Typography>
<Typography variant="body2" color="text.secondary">
<List>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<BadgeIcon />
</ListItemIcon>
<ListItemText primary="Name" />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<EmailIcon />
</ListItemIcon>
<ListItemText primary="Email" />
</ListItemButton>
</ListItem>
</List>
<Typography gutterBottom variant="h6" component="div">
Purchase History
</Typography>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Product</TableCell>
<TableCell align="right">Quantity</TableCell>
<TableCell align="right">Price</TableCell>
<TableCell align="right">Date Sold</TableCell>
<TableCell align="right">Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell component="th" scope="row">Mats
</TableCell>
<TableCell align="right">2</TableCell>
<TableCell align="right">$500</TableCell>
<TableCell align="right">1/12/23</TableCell>
<TableCell align="right">More</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Typography>
</CardContent>
</CardActionArea>
</Card>
<Button className="graphic2 btn-8 " style={{display: 'block', margin: 'auto', marginBottom: '3rem' }} onClick={logOut}>Logout</Button>
<Footer />
</>
)
}
為此,您必須在用戶登錄時將登錄 state 的用戶保存在 redux 中(因為您在項目中使用 redux)或本地存儲。
let res = await login({ email, password });
if (res.data) {
console.log(
"SAVE USER RES IN REDUX AND LOCAL STORAGE AND THEN REDIRECT"
);
// console.log(res.data);
//save user and token to local storage
window.localStorage.setItem("auth", JSON.stringify(res.data));
//save user and token to redux
dispatch({
type: "LOGGED_IN_USER",
payload: res.data,
});
history.push("/Home2");
}
之后,您可以在 redux 的幫助下檢查用戶是否可以登錄,從而在您的按鈕上應用 if/else 條件。
const { auth } = useSelector((state) => ({ ...state }));
if(auth != null){
<NavLink to="/Home2" className="btn btn-outline-dark m-2 graphic2 btn-8"style={{color: 'black', padding:'0.3rem'}}><i className="fa fa-user-plus mr-1"></i> Home</NavLink>
}
else{
<NavLink to="/login" className="btn btn-outline-dark m-2 graphic2 btn-8"style={{color: 'black', padding:'0.3rem'}}><i className="fa fa-user-plus mr-1"></i> Account</NavLink>
}
我希望這可以解決您手頭的問題。
在 Navbar.jsx 文件的頂部,添加一個常量以獲取登錄用戶
假設我們從上下文中獲取用戶
const { user } = useContext(UserContext);
...
// next at the bottom for the {/* Account Info */} part convert the second line to
{user ? (<NavLink to="/login" className="btn btn-outline-dark m-2 graphic2 btn-8"style={{color: 'black', padding:'0.3rem'}}><i className="fa fa-user-plus mr-1"></i> Account</NavLink>) : (<NavLink to="/Home2" className="btn btn-outline-dark m-2 graphic2 btn-8"style={{color: 'black', padding:'0.3rem'}}><i className="fa fa-user-plus mr-1"></i> Account</NavLink>)
我們使用條件渲染根據用戶是否登錄來渲染不同的導航鏈接
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.