首页 > 解决方案 > 如何使用 React-Router (TypeScript) 使我的登录功能与 React 功能组件一起使用?

问题描述

我在这里问了一个类似的问题。 与那个问题的不同之处在于这个问题即将解决与 Reacts 功能组件相同的问题,而我的另一个问题是如何通过具有状态的 React 类组件来解决它withRouter(仍然没有答案)。

我想要实现的是创建一个非常简单的登录页面。我已阅读并遵循https://reacttraining.com/react-router/web/example/auth-workflow上的教程,但我尝试使用我自己的代码来完成它,但我无法让它工作。按下登录按钮时,我永远不会进入登录页面。重定向过程似乎不起作用。

我错过了什么?

应用程序.tsx

import * as React from "react";
import SecretPage from "./secretpage";
import Login from "./loginpage";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Redirect
} from "react-router-dom";
import "./styles.css";

export default function Layout() {
  return (
    <Router>
      <Switch>
        <Route path="/login">
          <Login />
        </Route>
        <Route path="/">
          <Redirect to="/login" />;
        </Route>
        <Route path="/secret">
          <SecretPage />
        </Route>
      </Switch>
    </Router>
  );
}

登录.tsx

import * as React from "react";
import { MouseEvent, useState } from "react";
import { useLocation } from "react-router";
import { useHistory, Redirect, Route } from "react-router-dom";
import * as H from "history";

function onLogin({
  e,
  setAuthenticated,
  history,
  from,
}: {
  e?: MouseEvent<HTMLInputElement>;
  setAuthenticated: (b: boolean) => void;
  history: H.History;
  from: H.Location;
}) {

 authenticate().then(res => {
    if (res) {
      console.log("Logging in -> secretpage, from: " + JSON.stringify(from));
      setAuthenticated(true);
      history.replace(from);
    }
  });
}

function authenticate(): Promise<boolean> {
  return Promise.resolve(true);
}

export default function Login() {
  const [isAuthenticated, setAuthenticated] = useState(false);
  let history = useHistory();
  let location = useLocation();

  let { from } = location.state || { from: { pathname: "/" } };

  if (isAuthenticated) {
    console.log("Now authenticaed:" + JSON.stringify(location));

    return (
      <Route path="/secret">
        <Redirect to={{
          pathname: "/secret",
          state: { from: location }
        }} />
      </Route>
    )

  }

  return (
    <div className="login">
      <br />
      <input
        type="button"
        value="Log in to secret page"
        onClick={e => onLogin({ e, setAuthenticated, history, from})}
      />
    </div>
  );
}

秘密页面.tsx

import * as React from "react";

export default function SecretPage() {
  console.log("Rendering secret page");
  return (
    <div className="secretPage">
      <h1>Welcome to secret page</h1>
    </div>
  );
}

标签: reactjstypescriptreact-router

解决方案


在您的 login.tsxRedirect中不需要包装在Route组件中。您可以在 reactraining 附加的示例中找到。你可以看到Redirect被用作RenderProp. 在此处
查找有关渲染道具的更多信息

同样,在您app.tsx 更改 Route 路径的顺序时:

<Route path="/">
  <Redirect to="/login" />;
</Route>
<Route path="/secret">
 <SecretPage />
</Route>

至:

<Route path="/secret">
  <SecretPage />
</Route>
<Route path="/">
  <Redirect to="/login" />
</Route>

当您将代码包装Switchapp.tsx. 它将始终采用第一个匹配的路线。在你的情况下,它总是/. 它有重定向。所以你被重定向登录。当您路由到/secret.


推荐阅读