繁体   English   中英

React App 中未设置私有路由

[英]Private Routing is not getting set in React App

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

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

我尝试过类似的事情,如果令牌是 null 那么它应该保留在登录表单上,如果令牌不是 null 然后 go 到主页但这样做不是设置我的路由。

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

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

这是我的代码。

登录.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;

应用程序.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;

您应该为 Route 创建单独的组件,例如 PrivateRoute 并将您的组件包装在 PrivateRoute

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

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

示例:这会获取用户尝试访问的当前位置,并将其在路由 state 中传递到登录路由,以便用户可以被重定向他们最初尝试访问的路由。 经过身份验证后, 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>

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

完整的沙盒代码:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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