使用react-router-dom成功进行身份验证后将用户重定向到他们请求的页面

2023-11-26

我构建了一个公共路由组件,用于在用户未经身份验证时显示登录信息。每当未登录的用户单击受保护的路由时,他将被重定向到可以输入凭据的登录页面。我想要一种编程方式,这样如果他使用正确的凭据登录,他应该被重定向到他首先尝试访问的页面。例如,如果用户请求配置文件页面,他应该在登录后被重定向到该页面,如果用户请求设置页面,也会发生同样的情况。

截至目前,我只能将它们重定向到主路径/。有什么方法可以使用重定向,以便它知道用户请求的路径吗?

这是我当前的公共路线组件代码

export const PublicRoute = ({
    isAuthenticated,
    component: Component,
    ...rest
}: PublicRouteProps) => (
    <Route
        {...rest}
        component={(props: any) => {
            console.log(props.path);
            return isAuthenticated.auth ? (
                <Redirect to='/' />
            ) : (
                <div>
                    <Component {...props} />
                </div>
            );
        }}
    />
);
const mapStateToProps = (state: ReduxStoreState) => ({
    isAuthenticated: state.isAuthenticated
});

export default connect(mapStateToProps)(PublicRoute);


你的问题不能那么容易回答。基本上,您需要记住用户想要访问哪个路径,以便在用户成功通过身份验证后重定向到该路径。

我已经为你创建了一个例子here。您可以在下面找到该示例的解释和一些代码。

因此,如果用户未经过身份验证,我们将设置应用程序状态的路径。我会修改你的ProtectedRoute对此:

import { useEffect } from 'react';
import { Redirect, Route, RouteProps, useLocation } from 'react-router';

export type ProtectedRouteProps = {
  isAuthenticated: boolean;
  authenticationPath: string;
  redirectPath: string;
  setRedirectPath: (path: string) => void;
} & RouteProps;

export default function ProtectedRoute({isAuthenticated, authenticationPath, redirectPath, setRedirectPath, ...routeProps}: ProtectedRouteProps) {
  const currentLocation = useLocation();

  useEffect(() => {
    if (!isAuthenticated) {
      setRedirectPath(currentLocation.pathname);
    }
  }, [isAuthenticated, setRedirectPath, currentLocation]);

  if(isAuthenticated && redirectPath === currentLocation.pathname) {
    return <Route {...routeProps} />;
  } else {
    return <Redirect to={{ pathname: isAuthenticated ? redirectPath : authenticationPath }} />;
  }
};

为了记住身份验证和重定向路径,我将基于以下模型创建一个上下文:

export type Session = {
  isAuthenticated?: boolean;
  redirectPath: string;
}

export const initialSession: Session = {
  redirectPath: ''
};

据此,上下文如下所示:

import { createContext, useContext, useState } from "react";
import { initialSession, Session } from "../models/session";

export const SessionContext = createContext<[Session, (session: Session) => void]>([initialSession, () => {}]);
export const useSessionContext = () => useContext(SessionContext);

export const SessionContextProvider: React.FC = (props) => {
  const [sessionState, setSessionState] = useState(initialSession);
  const defaultSessionContext: [Session, typeof setSessionState]  = [sessionState, setSessionState];

  return (
    <SessionContext.Provider value={defaultSessionContext}>
      {props.children}
    </SessionContext.Provider>
  );
}

现在您需要使此上下文可供您的应用程序使用:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './containers/App';
import { SessionContextProvider } from './contexts/SessionContext';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <SessionContextProvider>
        <App />
      </SessionContextProvider>
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

在您的主容器中,您可以应用受保护的路由:

import ProtectedRoute, { ProtectedRouteProps } from "../components/ProtectedRoute";
import { useSessionContext } from "../contexts/SessionContext";
import { Route, Switch } from 'react-router';
import Homepage from "./Homepage";
import Dashboard from "./Dashboard";
import Protected from "./Protected";
import Login from "./Login";

export default function App() {
  const [sessionContext, updateSessionContext] = useSessionContext();

  const setRedirectPath = (path: string) => {
    updateSessionContext({...sessionContext, redirectPath: path});
  }

  const defaultProtectedRouteProps: ProtectedRouteProps = {
    isAuthenticated: !!sessionContext.isAuthenticated,
    authenticationPath: '/login',
    redirectPath: sessionContext.redirectPath,
    setRedirectPath: setRedirectPath
  };

  return (
    <div>
      <Switch>
        <Route exact={true} path='/' component={Homepage} />
        <ProtectedRoute {...defaultProtectedRouteProps} path='/dashboard' component={Dashboard} />
        <ProtectedRoute {...defaultProtectedRouteProps} path='/protected' component={Protected} />
        <Route path='/login' component={Login} />
      </Switch>
    </div>
  );
};

2021 年 3 月更新

我已经更新了上面的答案。从外部组件设置状态时,React 抛出错误。另外,以前的解决方案在以下情况下不起作用/路径未受保护。这个问题应该得到解决。

另外我还创建了React Router 6 的示例.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用react-router-dom成功进行身份验证后将用户重定向到他们请求的页面 的相关文章

随机推荐

  • MySQL 中的基数是什么?

    MySQL 中的基数是什么 请用简单的 非技术性的语言进行解释 如果任何表的索引详细信息显示字段的基数group id为11 那么这意味着什么呢 最大基数 所有值都是唯一的 最小基数 所有值都相同 有些列被称为高基数列 因为它们有约束 例如
  • Python:覆盖 __new__ 中的 __init__ 参数

    我有一个 new 方法如下 class MyClass object def new cls args new args args sort prev args pop 0 while args next args pop 0 if pre
  • 在反应中下载文件

    我有一个使用 Laravel 创建的 Restful API 该 API 如下所示 http 127 0 0 1 8000 api file pdf id 这是我的下载代码 public function pdfDownload id pd
  • “日期”的默认值无效

    我想将日期设置为mysql中日期的默认值 不是时间戳 但出现以下错误 ALTER TABLE RMS transactionentry CHANGE Date Date DATE DEFAULT NOW NOT NULL Error Inv
  • 如何保持响应图像相同的高度?

    我正在制作一个网页 其中有一排并排有封面照片和个人资料图片 我将它们都放在不同大小网格的引导行中 但是 个人资料图片总是低于封面照片 它的高度更大 如何让它们保持响应 但高度相同 我的最终目标是让它们看起来像一条带 之间有填充 然后当窗口大
  • 每次运行硒测试时如何增加字段值?

    每次通过 Selenium IDE 运行 Selenium 测试时 是否有任何简单的方法可以将字段值增加 1 Command Type Target some kind of id Value number 1 EDIT 1 感谢克罗森沃尔
  • 通过 server.execute 传递参数?

    可以通过传递参数server execute 外汇 我在我的site asp我需要的 IF 场景functions asp a something id 123被执行 这可能吗 在 site asp 上 dim id id 123 if b
  • 命令“npm start”不执行任何操作

    进入后npm start在我的 Node 项目的目录中 我看到旋转的管道符号 表明 npm 正在加载 然而 该图形会无限期地显示 并且什么也不会发生 没有提供错误消息 我该如何解决或至少诊断这个问题 My 包 json如下 name Pro
  • HTML5 和 Amazon S3 分段上传

    是否可以使用 HTML 5 File API 例如 这个库 https github com 23 resumable js 与 S3 分段上传功能结合使用 http docs aws amazon com AmazonS3 latest
  • Django 头痛与简单的非 ASCII 字符串

    我刚刚创建了以下模型 class Categoria models Model nombre models CharField max length 30 padre models ForeignKey self blank True nu
  • 如何对数组进行降序排序?

    我有一个数组 a 0 9 6 12 1 我需要一种按降序排序的方法 a 12 9 6 1 0 为了按升序排序 我有一个 Ruby 函数a to a sort 我正在寻找一个函数来按降序对数组进行排序 如下所示 a 0 9 6 12 1 so
  • Windows 10 的应用内存限制是多少?

    Windows Phone 8 1 的应用程序内存限制可以在 MSDN 上轻松找到 但我似乎无法找到有关 Windows 10 尤其是 Windows 10 Mobile 上应用程序内存限制的明确信息 每个设备系列 Xbox 台式机 手机
  • Webview shouldOverrideUrlLoading 没有被调用

    我正在制作一个电子书阅读器 它使用 epub 格式将书籍加载到网络视图中 在某些书中 有指向同一章中某些部分的锚链接 每一章都以 html 形式加载 这就是链接的样子 file storage sdcard0 Android data co
  • 如何用 JSON 表示稀疏数组?

    我有一个稀疏数组 我想用 JSON 表示 例如 10 gt 100 1 gt 102 3 gt 44 12 gt 87 12345 gt 0 我怎样才能做到这一点 我可以这样做吗 您可以将其表示为一个简单的对象 10 100 1 102 3
  • 关联关系中的角色名称

    从 UML 圣经来看 大约role 角色 角色名称解释了对象如何参与关系 每个对象都需要保存对关联对象的引用 该引用保存在对象内的属性值中 当只有一个关联时 则只有一个属性持有引用 这句话是什么意思呢 谁能举个例子来解释一下吗 Roles
  • 如何在 Symfony5 中为学说配置 apcu

    在 Symfony4 中 我使用以下配置进行教义 apcu 缓存 doctrine orm auto mapping true auto generate proxy classes false metadata cache driver
  • C++ 将数字从零舍入

    你好 我想在 C 中像这样舍入双数 远离零 4 2 gt 5 5 7 gt 6 7 8 gt 8 34 2 gt 35 做到这一点的有效方法是什么 inline double myround double x return x lt 0 f
  • R Shiny 应用程序中的延迟执行

    RShiny 应用程序的某些部分是否可能以延迟方式执行 就像 Windows 服务中的延迟启动一样 让我详细说明一下 我有一个带有选项卡的闪亮应用程序 每个选项卡的侧边栏面板上都有一堆单选按钮 单击每个单选按钮都会弹出一个报告 我的设置就是
  • 从 TextTransform.exe 获取参数值到模板中

    当我使用 TextTransform exe 从模板生成代码时 我找不到一些示例如何使用参数 a 在MSDN参数 a 的描述如下 指定指令的参数 处理器可以查询为 名称 值对 该指令 处理器和标识符是可选的 这允许指定参数 对于任何指令处理
  • 使用react-router-dom成功进行身份验证后将用户重定向到他们请求的页面

    我构建了一个公共路由组件 用于在用户未经身份验证时显示登录信息 每当未登录的用户单击受保护的路由时 他将被重定向到可以输入凭据的登录页面 我想要一种编程方式 这样如果他使用正确的凭据登录 他应该被重定向到他首先尝试访问的页面 例如 如果用户