【问题标题】:react router v6 - routing is not getting set correctly反应路由器 v6 - 路由设置不正确
【发布时间】:2022-01-04 18:05:36
【问题描述】:

我想在我的 react 应用中设置私有路由。我创建了两个组件。 ParivateRoute.js 和 ParivateRoute.js 我在 App.js 中导入这两个组件。我正在基于令牌设置私有路由,如果令牌存在,则设置私有路由,如果令牌为空,则应设置公共路由。

我尝试了一些代码,设置了我的私有路由,但没有设置我的公共路由。

我在公共路由中面临这个问题,每当登录表单(电子邮件和密码)的两个字段都是空的并且我点击登录按钮时,路径就会像这样http://localhost:3000/?email=&password=

虽然不应该这样。每当我点击登录按钮并且我的两个字段(电子邮件和密码)都是空的时,我希望路径是这样的 http://localhost:3000/

所以我不知道如何获得它。我想 帮助正确设置路由路径。

请提供更多帮助,我还想在登录和注册等多个组件上设置公共路由。那我该怎么做呢?

下面是我的代码。

Login.js

import React, { useState } from "react";
import { Form, Button } from "react-bootstrap";
import { useNavigate, Link } from "react-router-dom";
import RequireAuth from "./PrivateRoute";

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);
        toUsersTable();
      } else {
        console.log("failure");
        return false;
      }
    });
    setUserData(initialValues);
  };

  const navigateToUsersTable = useNavigate();
  const toUsersTable = () => {
    return navigateToUsersTable("/usersTable");
  };

  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>
      <RequireAuth authenticateUser={authenticateUser} />
    </>
  );
};
export default Login;

PrivateRoute.js

import React from "react";
import { Route, Navigate, Routes } from "react-router-dom";
import Login from "./Login";
import UsersTable from "./UsersTable";

const PrivateRoute = ({ ...rest }) => {
  console.log("rest is", { ...rest });
  const token = JSON.parse(sessionStorage.getItem("token"));
  console.log(token);
  return (
    <Routes>
      <Route {...rest} element={token ? <UsersTable /> : <Navigate to="/" />} />
    </Routes>
  );
};

export default PrivateRoute;

PublicRoute.js

import React from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import Login from "./Login";

const PublicRoute = ({ ...rest }) => {
  const token = JSON.parse(sessionStorage.getItem("token"));
  return (
    <Routes>
      <Route
        {...rest}
        element={token ? <Navigate to="/usersTable" /> : <Login />}
      />
    </Routes>
  );
};
export default PublicRoute;

App.js

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

const App = () => {
  return (
    <>
      <Layout>
        <Router>
          <Routes>
            <Route element={<SignUp />} exact path="/signUp" />
          </Routes>
          <PublicRoute element={<Login />} exact path="/" />
          <PrivateRoute element={<UsersTable />} exact path="/usersTable" />
        </Router>
      </Layout>
    </>
  );
};

export default App;

提前致谢。

【问题讨论】:

  • 您的问题似乎存在一些问题,可能难以理解(两个组件都称为同一个文件,在同一个问题中提出多个问题等)。也就是说,您的代码示例非常清晰且很有帮助。我建议您查看this Medium post,因为它可能会引导您朝着正确的方向前进。
  • Dykotomee,感谢您的关注。我还从同一个 Medium 帖子中获得了帮助,以完成我的代码。

标签: javascript reactjs react-router react-router-dom


【解决方案1】:

当您单击登录按钮时,URL 会更改为http://localhost:3000/?email=&amp;password= bcuz 在您的表单上您没有指定它应该使用的method,默认值为GET。这就是为什么 yow 表单输入出现在 url 中的原因,如果您不想在 url 中发送表单字段,则需要将方法设置为 post method="POST"。现在它们的字段不会在 url 中发送,但由于我们不是 90 年代,所以您不必这样做。您需要做的是防止默认行为。

从按钮的 onClickHandler 中移除并将其添加到表单中

const onSubmit = event => {
event.preventDefault();
authenticateUser();
};

...
return(
<Form onSubmit={onSubmit}>
...
 <Button variant="primary" type="submit">Login</Button>

但不是 onClick 而是 onSubmit 确保 preventDefault

【讨论】:

    【解决方案2】:

    react-router-dom 中,自定义路由组件已被淘汰、替换或更喜欢处理业务逻辑并呈现children 属性或Outlet 用于嵌套路由或声明性重定向的包装组件。

    由于您询问要在“私有”路由上放置多个组件,我建议使用 Outlet 实现。

    const PrivateWrapper = () => {
      const token = JSON.parse(sessionStorage.getItem("token"));
      console.log(token);
    
      return token ? <Outlet /> : <Navigate to="/login" replace />;
    };
    
    const PublicWrapper = () => {
      const token = JSON.parse(sessionStorage.getItem("token"));
    
      return token ? <Navigate to="/" replace /> : <Outlet />;
    };
    

    ...

    const App = () => {
      return (
        <>
          <Layout>
            <Router>
              <Routes>
                <Route path="/" element={<div>Home Page</div>} />
                <Route path="/signUp" element={<SignUp />} />
                <Route element={<PublicWrapper />}>
                  <Route path="/login" element={<Login />} />
                  .... other public routes ....
                </Route>
                <Route element={<PrivateWrapper />}>
                  <Route path="/usersTable" element={<UsersTable />} />
                  .... other private routes ....
                </Route>
              </Routes>
            </Router>
          </Layout>
        </>
      );
    };
    

    我看不到您在哪里发出任何命令式导航,包括任何 queryString 参数,但据我所知,您并没有阻止提交时的默认表单操作。将提交处理程序移动到Form 组件的onSubmit 事件处理程序,并在提交事件对象上调用preventDefault

    const authenticateUser = event => {
      event.preventDefault();
      ...
    };
    
    ...
    
    <Form className="loginForm" onSubmit={authenticateUser}>
      ...
      <Button
        variant="primary"
        type="submit"
      >
        Login
      </Button>
      ...
    </Form>
    

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 2021-10-17
      • 1970-01-01
      • 2020-07-29
      • 2021-03-29
      • 1970-01-01
      • 2020-10-04
      • 2022-01-11
      • 2021-04-27
      相关资源
      最近更新 更多