简体   繁体   中英

Private Routing is not getting set in React App

In my React app, when the user is successfully signed, his/her information is being saved in the local storage. And a token is being saved in the session storage only when the user is successfully logged in.

Now I know that the token will be in the session storage only if the user has successfully logged in. On the basis of this token I want to set up my private routing.

I have attempted something like that if token is null then it should remain on login form and if token is not null then go to home page But doing something like this is not setting my routing.

I think maybe I am doing some mistake with App.js file where I am running Router, Routes and Route or where I am checking token is null or not null I am making some mistake there.

please help me to rectify my mistake. Thanks.

Here is my code.

Login.js

import React, { useState } from "react";
import { Form, Button } from "react-bootstrap";
import { Link } from "react-router-dom";

const Login = ({ setTokenData }) => {
  const initialValues = {
    email: "",
    password: "",
  };

  const [userData, setUserData] = useState(initialValues);
  const authenticateUser = () => {
    const localInfo = JSON.parse(localStorage.getItem("signUpUser"));

    localInfo?.map((item) => {
      const userName = item.email;
      const userPassword = item.password;
      if (userName === userData.email && userPassword === userData.password) {
        console.log("success");
        const token = Math.random().toString(36).substr(2, 5);
        console.log("token is:", token);
        sessionStorage.setItem("token", JSON.stringify(token));
        setTokenData(token);
      } else {
        console.log("failure");
        return false;
      }
    });
    setUserData(initialValues);
  };

  return (
    <>
      <Form className="loginForm">
        <Form.Group className="mb-3" controlId="formBasicEmail">
          <Form.Label>Email Address</Form.Label>
          <Form.Control
            type="email"
            placeholder="Enter email"
            value={userData.email}
            name="email"
            onChange={(e) =>
              setUserData({ ...userData, [e.target.name]: e.target.value })
            }
          />
        </Form.Group>
        <Form.Group className="mb-3" controlId="formBasicPassword">
          <Form.Label>Password</Form.Label>
          <Form.Control
            type="password"
            placeholder="Password"
            name="password"
            value={userData.password}
            onChange={(e) =>
              setUserData({ ...userData, [e.target.name]: e.target.value })
            }
          />
        </Form.Group>
        <Form.Group className="mb-3" controlId="formBasicCheckbox"></Form.Group>

        <Button
          variant="primary"
          type="submit"
          onClick={() => authenticateUser()}
        >
          Login
        </Button>

        <div className="txtToSignUpBtn">
          <span>OR</span> <Link to="/signUp">Click here to Register</Link>
        </div>
      </Form>
    </>
  );
};
export default Login;

PrivateRoute.js

import React from 'react'
import { Navigate } from 'react-router-dom';
import Login from "./Login";
import Header from "./Header";

const getTokenData = () => {
    const token = JSON.parse(sessionStorage.getItem("token"));
    if (token) {
      return JSON.parse(sessionStorage.getItem("token"));
    } else {
      return null;
    }
  };
const RequireAuth = () => {
    const [tokenData, setTokenData] = useState(getTokenData());
if (tokenData === null) {
    return <Login setTokenData={setTokenData} />,
    <Navigate to='/' />
} else {
    return <Header setTokenData={setTokenData} />,
    <Navigate to='/home' />
}
        
export default RequireAuth;

App.js

import { Layout } from "antd";
import React from "react";
import SignUp from "./SignUp";
import Login from "./Login";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Header from "./Header";
import UsersTable from "./UsersTable";
import RequireAuth from "./PrivateRoute";

const AppWrapper = () => {
  return (
    <>
      <Layout>
        <Router>
          <Routes>
            <Route
              exact
              path="/home"
              element={
                <RequireAuth>
                  <Header />
                </RequireAuth>
              }
            />
            <Route exact path="/signUp" element={<SignUp />} />
            <Route exact path="/" element={<Login />} />
            <Route exact path="/usersTable" element={<UsersTable />} />
          </Routes>
        </Router>
      </Layout>
    </>
  );
};

export default AppWrapper;

you should create separated component for Route like PrivateRoute and wrap your component inside PrivateRoute

I wanted to provide you a code sample but i found a good example on the following website https://blog.netcetera.com/how-to-create-guarded-routes-for-your-react-app-d2fe7c7b6122

I think you're onto the right idea with the RequireAuth auth wrapper. I suggest aligning more closely with the RRDv6 route wrapper paradigm though. Have your RequireAuth simply check the session storage and render an Outlet if authenticated or a redirect to a login route if not.

Example: This grabs the current location a user is attempting to access and passes this in route state to the login route so a user can be redirected back to the route they were trying to access originally. When authenticated the Outlet renders nested Route components.

const RequireAuth = () => {
  const location = useLocation();

  const tokenData = getTokenData();

  return tokenData ? (
    <Outlet />
  ) : (
    <Navigate to="/login" state={{ from: location }} replace />
  );
};

Usage: Here the "/usersTable" is placed on a route nested in a route rendering the RequreAuth wrapper. If the user is unauthenticated and attempt to access this route they will be bounced over to the "/login" route to log in, and upon successful authentication will be redirected back to "/usersTable" .

<Routes>
  <Route path="/" element={<h1>Home</h1>} />
  <Route path="/signUp" element={<SignUp />} />
  <Route path="/login" element={<Login />} />
  <Route element={<RequireAuth />}>
    <Route path="/usersTable" element={<UsersTable />} />
  </Route>
</Routes>

编辑 private-routing-is-not-getting-set-in-react-app

Full sandbox code:

import {
  BrowserRouter as Router,
  Routes,
  Route,
  Link,
  Navigate,
  Outlet,
  useLocation,
  useNavigate
} from "react-router-dom";

const getTokenData = () => {
  return JSON.parse(sessionStorage.getItem("token"));
};

const RequireAuth = () => {
  const location = useLocation();

  const tokenData = getTokenData();

  return tokenData ? (
    <Outlet />
  ) : (
    <Navigate to="/login" state={{ from: location }} replace />
  );
};

const Header = () => (
  <ul>
    <li>
      <Link to="/">Home</Link>
    </li>
    <li>
      <Link to="/login">Login</Link>
    </li>
    <li>
      <Link to="/signUp">Sign Up</Link>
    </li>
    <li>
      <Link to="/usersTable">Users Table</Link>
    </li>
  </ul>
);

const SignUp = () => <h1>SignUp</h1>;
const UsersTable = () => <h1>UsersTable</h1>;

const Login = () => {
  const navigate = useNavigate();
  const { state } = useLocation();
  const { from = "/" } = state || {};

  const authenticate = () => {
    sessionStorage.setItem("token", JSON.stringify(true));
    navigate(from, { replace: true });
  };

  const deauthenticate = () => {
    sessionStorage.removeItem("token");
    navigate("/", { replace: true });
  };

  return (
    <>
      <h1>Login</h1>
      {getTokenData() ? (
        <button type="button" onClick={deauthenticate}>
          Log out
        </button>
      ) : (
        <button type="button" onClick={authenticate}>
          Log in
        </button>
      )}
    </>
  );
};

export default function App() {
  return (
    <Router>
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>

      <Header />
      <Routes>
        <Route path="/" element={<h1>Home</h1>} />
        <Route path="/signUp" element={<SignUp />} />
        <Route path="/login" element={<Login />} />
        <Route element={<RequireAuth />}>
          <Route path="/usersTable" element={<UsersTable />} />
        </Route>
      </Routes>
    </Router>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM