Home > Net >  React MongoDB E-Commerce website. If user is already logged in, how to redirect from "Account&q
React MongoDB E-Commerce website. If user is already logged in, how to redirect from "Account&q

Time:01-16

I am creating an E-Commerce website with React and MongoDB. So far I have a JSON that plugs in a list of products that someone can select and add to there cart for purchase. The design aspect is nearly finished and now I am working on the functionally.

The Navbar that appears on every screen has an option for an "Account" button that redirects someone to the login page. Either they sign up for an account or if they already have an account then they enter there info and log in and are redirected to "Home2" account information page.

The issue I am facing is that if they are already logged in and they click "Account" button in the navbar then they are redirected back to the Log in page. I want to set it so if they click the "Account" button in the navbar after they are signed in then they are redirected to the "Home2" account info page. Id imagine it is some type of if else statement?

The Index.JS page

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>
);

The Navbar.Jsx page where the account button is

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

The login page

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;

The Home2 page

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 />
</>
)
}

CodePudding user response:

For this to work you have to save the user logged in state in the redux(because you are using redux in your project) or local storage at the time of user login .

  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");
  }

Afterwards you can apply the if/else condition on you button by checking if the user is available in logged in or not with the help of redux.

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>
 }

I hope this resolves your problem at hand.

CodePudding user response:

At the top in your Navbar.jsx file you add a constant for getting the logged in user

Assuming we get the user from context

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>)

We use conditional rendering to render different nav links depending on wheather the user is logged in or not

  • Related