使用 react-router-dom 成功验证后将用户重定向到他们请求的页面 [英] Redirecting a user to the page they requested after successful authentication with react-router-dom

查看:15
本文介绍了使用 react-router-dom 成功验证后将用户重定向到他们请求的页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

export const PublicRoute = ({已认证,组件:组件,...休息}: PublicRouteProps) =>(<路线{...休息}组件={(道具:任何)=>{console.log(props.path);返回 isAuthenticated.auth ?(<重定向到='/'/>) : (<div><组件{...道具}/>

);}}/>);const mapStateToProps = (state: ReduxStoreState) =>({isAuthenticated: state.isAuthenticated});导出默认连接(mapStateToProps)(公共路由);

解决方案

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

我为您创建了一个示例 这里.您可以在下面找到该示例中的说明和一些代码.

因此,如果用户未通过身份验证,我们将设置应用程序状态的路径.我会将您的 ProtectedRoute 修改为:

import { useEffect } from 'react';从'react-router'导入{重定向,路由,RouteProps,useLocation};导出类型 ProtectedRouteProps = {isAuthenticated:布尔值;身份验证路径:字符串;重定向路径:字符串;setRedirectPath: (path: string) =>空白;&路由道具;导出默认函数 ProtectedRoute({isAuthenticated, authenticationPath, redirectPath, setRedirectPath, ...routeProps}: ProtectedRouteProps) {const currentLocation = useLocation();useEffect(() => {如果 (!isAuthenticated) {setRedirectPath(currentLocation.pathname);}}, [isAuthenticated, setRedirectPath, currentLocation]);if(isAuthenticated && redirectPath === currentLocation.pathname) {返回 <Route {...routeProps}/>;} 别的 {返回 <重定向到={{ 路径名:isAuthenticated ?重定向路径:身份验证路径 }}/>;}};

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

导出类型会话 = {isAuthenticated?:布尔值;重定向路径:字符串;}导出常量初始会话:会话 = {重定向路径:''};

根据上下文看起来是这样的:

import { createContext, useContext, useState } from react";从../models/session"导入 { initialSession, Session };export const SessionContext = createContext<[Session, (session: Session) =>void]>([initialSession, () => {}]);export const useSessionContext = () =>使用上下文(会话上下文);export const SessionContextProvider: React.FC = (props) =>{const [sessionState, setSessionState] = useState(initialSession);const defaultSessionContext: [Session, typeof setSessionState] = [sessionState, setSessionState];返回 (<SessionContext.Provider value={defaultSessionContext}>{props.children}</SessionContext.Provider>);}

现在你需要让你的应用可以使用这个上下文:

从'react'导入React;从 'react-dom' 导入 ReactDOM;从'./containers/App'导入应用程序;从 './contexts/SessionContext' 导入 { SessionContextProvider };从'react-router-dom'导入{ BrowserRouter};ReactDOM.render(<React.StrictMode><浏览器路由器><SessionContextProvider><应用程序/></SessionContextProvider></BrowserRouter></React.StrictMode>,document.getElementById('root'));

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

import ProtectedRoute, { ProtectedRouteProps } from "../components/ProtectedRoute";import { useSessionContext } from "../contexts/SessionContext";从反应路由器"导入 { Route, Switch };从./主页"导入主页;从./Dashboard"导入仪表板;import Protected from "./Protected";从./Login"导入登录;导出默认函数 App() {const [sessionContext, updateSessionContext] = useSessionContext();const setRedirectPath = (path: string) =>{updateSessionContext({...sessionContext, redirectPath: path});}const defaultProtectedRouteProps: ProtectedRouteProps = {isAuthenticated: !!sessionContext.isAuthenticated,身份验证路径:'/登录',重定向路径:sessionContext.redirectPath,设置重定向路径:设置重定向路径};返回 (<div><开关><Route exact={true} path='/' component={Homepage}/><ProtectedRoute {...defaultProtectedRouteProps} path='/dashboard' component={Dashboard}/><ProtectedRoute {...defaultProtectedRouteProps} path='/protected' component={Protected}/><Route path='/login' component={Login}/></开关>

);};

2021 年 3 月更新

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

另外我已经创建了一个例子用于 React 路由器 6.

I have constructed a Public route component for logging in to show up if the user is not authenticated. Whenever a user that is not logged clicks on a protected route, he will be redirected to the login page where he can enter the credentials. I want a programmatic way so that if he logged in with the correct credentials, he should be redirected to the page that he tried to access at the first place. For example if the user requested the profile page, he should be redirected to it after logging in, if the user requested the settings page, the same would happen.

As of currently, I can only redirect them to the home path /. Is there any way I can use Redirect so that it knows the path the user requested?

Here is my current code for the Public Route component

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

解决方案

You question cannot be answered that easily. Basically you need to remember, which path a user wanted to access, so you can redirect to that path, after the user successfully authenticated.

I've created you an example here. The explanation and some code from that example you can find below.

So if the user is not authenticated, we set the path to the app state. I would modify your ProtectedRoute to this:

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

To remember the authentication and the redirection path I would create a context based on the following model:

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

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

According to that the context looks like this:

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

Now you need to make this context available to your app:

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

In your main container you can apply the protected routes:

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

Update March 2021

I've updated my answer above. React was throwing an error when setting the state from a foreign component. Also the previous solution didn't work when / path was not protected. This issues should be fixed.

Additionally I've created an example for React Router 6.

这篇关于使用 react-router-dom 成功验证后将用户重定向到他们请求的页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆