【问题标题】:Private Routing is not getting set in React AppReact App 中未设置私有路由
【发布时间】:2022-01-03 17:05:40
【问题描述】:

在我的 React 应用程序中,当用户成功签名后,他/她的信息将保存在本地存储中。只有当用户成功登录时,才会将令牌保存在会话存储中。

现在我知道只有当用户成功登录时,令牌才会在会话存储中。基于这个令牌,我想设置我的私有路由。

我尝试过类似的事情,如果令牌为空,那么它应该保留在登录表单上,如果令牌不为空,则转到主页但是这样做并没有设置我的路由。

我想也许我在运行路由器、路由和路由的 App.js 文件中犯了一些错误,或者我正在检查令牌是否为空,我在那里犯了一些错误。

请帮助我纠正我的错误。谢谢。

这是我的代码。

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;

【问题讨论】:

    标签: javascript reactjs react-router react-props


    【解决方案1】:

    您应该像 PrivateRoute 一样为 Route 创建单独的组件,并将您的组件包装在 PrivateRoute 中

    我想为您提供一个代码示例,但我在以下网站https://blog.netcetera.com/how-to-create-guarded-routes-for-your-react-app-d2fe7c7b6122找到了一个很好的示例

    【讨论】:

    【解决方案2】:

    我认为您使用RequireAuth auth 包装器的想法是正确的。不过,我建议更紧密地与 RRDv6 路由包装器范例保持一致。让您的 RequireAuth 简单地检查会话存储,如果经过身份验证,则呈现 Outlet,否则重定向到登录路由。

    示例:这会获取用户尝试访问的当前位置并将其以路由状态传递给登录路由,以便用户可以被重定向返回到他们最初尝试访问的路由。通过身份验证后,Outlet 呈现嵌套的 Route 组件。

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

    用法:这里"/usersTable" 被放置在嵌套在渲染RequreAuth 包装器的路由中的路由上。如果用户未经身份验证并尝试访问此路由,他们将被退回到"/login" 路由进行登录,并且在身份验证成功后将被重定向回"/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>
    

    完整的沙盒代码:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-04
      • 2021-06-04
      • 2018-03-13
      • 2020-08-13
      • 1970-01-01
      • 2022-01-17
      • 1970-01-01
      • 2020-06-26
      相关资源
      最近更新 更多