簡體   English   中英

React MongoDB 電子商務網站。 如果用戶已經登錄,如何從“帳戶”按鈕重定向到用戶信息而不是登錄頁面?

[英]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&nbsp;(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM