当前位置: 首页 > 面试题库 >

如何使用TypeScript和React-Router 4和5重写受保护/专用路由?

纪辰沛
2023-03-14
问题内容

我试图使用TypeScript <PrivateRoute>在react-router
文档中创建一个描述。谁能帮我吗?

react-router文档中的privateRoute:

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{pathname: '/login', state: { from: props.location }
   }}/>
  )
 )}/>
)

以下是我的TypeScript版本(无法使用):

const PrivateRoute = (theProps: { path: string, component: React.SFC<RouteComponentProps<any> | undefined> | React.ComponentClass<RouteComponentProps<any> | undefined> }) => {
    return <Route path={theProps.path} render={props => (
        fakeAuth.isAuthenticated ? (
            <React.Component {...theProps} /> <!-- **** It will raise error *** -->
        ) : (
                <Redirect to={{
                    pathname: '/',
                    state: { from: props.location }
                }} />
            )
    )} />
}

<React.Component {...thisProps} />是不对的。错误是:NodeInvocationException:inst.render不是函数TypeError:inst.render不是函数


问题答案:

该错误可能与打字和渲染中的隐式返回有关。解决此问题时,最终会得到如下结果:

const PrivateRoute = ({component, isAuthenticated, ...rest}: any) => {
    const routeComponent = (props: any) => (
        isAuthenticated
            ? React.createElement(component, props)
            : <Redirect to={{pathname: '/login'}}/>
    );
    return <Route {...rest} render={routeComponent}/>;
};

该组件可以这样使用:

<PrivateRoute
    path='/private'
    isAuthenticated={this.props.state.session.isAuthenticated}
    component={PrivateContainer}
/>

上面的解决方案有一些缺点。其中之一是您失去类型安全性。

最好扩展Route组件是更好的主意。

import * as React from 'react';
import {Redirect, Route, RouteProps} from 'react-router';

export interface ProtectedRouteProps extends RouteProps {
    isAuthenticated: boolean;
    authenticationPath: string;
}

export class ProtectedRoute extends Route<ProtectedRouteProps> {
    public render() {
        let redirectPath: string = '';
        if (!this.props.isAuthenticated) {
            redirectPath = this.props.authenticationPath;
        }

        if (redirectPath) {
            const renderComponent = () => (<Redirect to={{pathname: redirectPath}}/>);
            return <Route {...this.props} component={renderComponent} render={undefined}/>;
        } else {
            return <Route {...this.props}/>;
        }
    }
}

因此,您可以使用以下组件:

const defaultProtectedRouteProps: ProtectedRouteProps = {
    isAuthenticated: this.props.state.session.isAuthenticated,
    authenticationPath: '/login',
};

<ProtectedRoute
    {...defaultProtectedRouteProps}
    exact={true}
    path='/'
    component={ProtectedContainer}
/>

更新(2019年11月)

如果您喜欢编写功能组件,则可以采用非常相似的方式来完成。这也适用于React Router 5:

import * as React from 'react';
import { Redirect, Route, RouteProps } from 'react-router';

export interface ProtectedRouteProps extends RouteProps {
  isAuthenticated: boolean;
  isAllowed: boolean;
  restrictedPath: string;
  authenticationPath: string;
}

export const ProtectedRoute: React.FC<ProtectedRouteProps> = props => {
  let redirectPath = '';
  if (!props.isAuthenticated) {
    redirectPath = props.authenticationPath;
  }
  if (props.isAuthenticated && !props.isAllowed) {
    redirectPath = props.restrictedPath;
  }

  if (redirectPath) {
    const renderComponent = () => <Redirect to={{ pathname: redirectPath }} />;
    return <Route {...props} component={renderComponent} render={undefined} />;
  } else {
    return <Route {...props} />;
  }
};

export default ProtectedRoute;

更新(2019年12月)

如果要将用户重定向到该用户首先要访问的路径,则需要记住该路径,这样您就可以在成功通过身份验证后进行重定向。以下答案将指导您完成该任务:



 类似资料:
  • 在< code>/users下,我有一些需要身份验证令牌的路由,还有一些不需要。为了实现这一点,我做了以下工作。 然后我按照以下方式安装这些路线。 当我向< code>/users发送POST时,它运行预期的路径,但是当< code>next()被调用时,< code > protected _ middleware 运行。这是因为它在标有“D”的行中找到了下一个< code>/users定义。

  • 我的API应用程序中有此路由: 在postman中,我执行如下api调用: URL用户?令牌=令牌 但这会带来: 如何在postman中使用令牌正确执行api调用?

  • 在服务器端,我有2个中间件——protect(登录了吗?)和restrictTo(检查用户的角色)。如果不允许,这些中间件会阻止用户或访客执行某些操作 但是如何在客户端保护路由呢?如果不允许我发布新消息,那么我应该被阻止进入 /newnote页面,这样我就看不到并填写表单。JWT令牌存储在带有http唯一标志的cookie中。因此我无法从Vue路由器访问令牌。将用户角色存储在Vuex中?那么如何在

  • 我希望使用基于UML模型的genmodel生成Java代码。 我正在使用Papyrus的Eclipse Oxygen,UML模型(使用了一些Ecore配置文件),以便使用GenModel向导生成Ecore,最终生成模型Java代码(标准Eclipse插件)。 我已将生成的源代码与手写的源代码分开,因此将避免+手动修改解决方案:) null

  • 我正在使用Mockito 1.9.5。我如何嘲笑从受保护的方法返回的内容?我有这个受保护的方法... 然而,当我尝试在JUnit中这样做时: 在最后一行,我得到一个编译错误“方法‘myMethod’不可见”如何使用Mockito来模拟受保护的方法?如果答案是这样,我愿意升级我的版本。

  • 我正在尝试在zookeeper和kafka之间设置kerberos标识。 我遵循了此处提供的配置步骤:https://docs.confluent.io/4.1.1/kafka/authentication_sasl_gssapi.html#sasl-gssapi经纪人。 Kafka代理成功连接到zookeeper集合,代理正在zNode上设置ACL。 在Zookeeper中,我可以看到znode