reactjs - 使用 Typescript 和 React 在私有(private)路由中传递组件 Prop

标签 reactjs typescript react-router

我正在使用来自 React Router v4 的 Route 组件的渲染 Prop ,使用 Typescript 和 React 实现经过身份验证的路由。

路线:

import React from 'react';
import { Switch, Route } from 'react-router-dom';
import { ROUTES } from 'utils/constants';
import HomePage from 'components/pages/Home';
import GuestLogin from 'components/pages/GuestLogin';
import ProfilePage from 'components/pages/Profile';
import NotFoundPage from 'components/pages/NotFound';
import ResetPassword from 'components/pages/ResetPassword';
import SetPassword from 'components/pages/SetPassword';
import LoginContainer from 'containers/Login';
import PrivateRoute from './PrivateRoute';

const Routes: React.FunctionComponent = () => (
  <Switch>
    <Route path={ROUTES.LOGIN} component={LoginContainer} exact></Route>
    <PrivateRoute
      path={ROUTES.HOME}
      component={HomePage}
    ></PrivateRoute>
    <Route path={ROUTES.GUEST_LOGIN} component={GuestLogin}></Route>
    <Route path={ROUTES.RESET_PASSWORD} component={ResetPassword}></Route>
    <Route path={ROUTES.SET_PASSWORD} component={SetPassword}></Route>
    <Route path={ROUTES.PROFILE} component={ProfilePage}></Route>
    <Route component={NotFoundPage}></Route>
  </Switch>
);

export default Routes;

私有(private)路线:

import React from 'react';    
import { useAppContext } from 'containers/App/AppContext';
import { RouteProps, Route, Redirect } from 'react-router-dom';
import { ROUTES } from 'utils/constants';

const PrivateRoute: React.FunctionComponent<RouteProps> = ({
  component: Component,
  ...routeProps
}) => {
  const { isSignedIn } = useAppContext();
  const ComponentToRender = Component as React.ElementType;
  return (
    <Route
      {...routeProps}
      render={(props) =>
        isSignedIn ? (
          <ComponentToRender {...props} />
        ) : (
          <Redirect to={ROUTES.LOGIN} />
        )
      }
    />
  );
};

export default PrivateRoute;

问题是我想调用 Prop 上的组件集,但是,每次我尝试这样做时,Typescript 都会抛出以下错误。

JSX element type 'Component' does not have any construct or call signatures.  TS2604

Image of the error

原因似乎是 Route 的组件类型不是 Typescript 所期望的类型,如此处解释:https://github.com/microsoft/TypeScript/issues/28631 ,因此我刚刚创建了一个具有新类型 (ComponentToRender) 的副本。

有没有更好的方法来实现这个?也许会覆盖 RouteProps 组件元素?

谢谢!

最佳答案

终于明白错误并解决了!关键是组件属性和渲染函数在类型方面的处理方式不同。 通过使用 RouteProps ,Typescript 编译器实际上将组件属性设置为 ComponentType(根据 RouterProps 为“组件”指定的类型),它不能用于渲染函数,如索引中所示。 d.ts 文件。

export interface RouteProps {
    location?: H.Location;
    component?: React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any>;
    render?: (props: RouteComponentProps<any>) => React.ReactNode;
    children?: ((props: RouteChildrenProps<any>) => React.ReactNode) | React.ReactNode;
    path?: string | string[];
    exact?: boolean;
    sensitive?: boolean;
    strict?: boolean;
}

只要将渲染函数移动到路由文件中而不使用 PrivateRoute 组件,这种行为就会变得明显。下面的代码按预期工作,因为编译器正确推断类型 (React.ReactNode)。

<Route
  path={ROUTES.POINTS_HISTORY}
  render={(props) =>
    isSignedIn ? <PointsTransactions /> : <Redirect to={ROUTES.LOGIN} />
  }
></Route>

因此,为了解决这个问题,我只是创建了一个新类型,其中只有我的用例所需的参数。

import React from 'react';

import { useAppContext } from 'containers/App/AppContext';
import { RouteProps, Route, Redirect } from 'react-router-dom';
import { ROUTES } from 'utils/constants';

type PrivateRouteProps = {
  path: RouteProps['path'];
  component: React.ElementType;
};
const PrivateRoute: React.FunctionComponent<PrivateRouteProps> = ({
  component: Component,
  ...routeProps
}) => {
  const { isSignedIn } = useAppContext();
  return (
    <Route
      {...routeProps}
      render={(props) =>
        isSignedIn ? <Component /> : <Redirect to={ROUTES.LOGIN} />
      }
    />
  );
};

export default PrivateRoute;

关于reactjs - 使用 Typescript 和 React 在私有(private)路由中传递组件 Prop ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63463502/

相关文章:

reactjs - 如何在 React-Native 中共享生成的二维码?

javascript - 像 Redux 一样构建 Mobx 项目

reactjs - Jest 模拟 window.scrollTo

reactjs - React 16.7 - React.SFC 现已弃用

javascript - React Router 中的多个可选参数

javascript - react 路由器用作 <Routes> 元素错误的子元素

reactjs - React.js 中的页面崩溃(读取未定义的属性)

css - ReactJS Material UI inkbar 不显示选项卡

javascript - `(this as any)` 在此 typescript 片段中意味着什么?

angular - 在服务返回值之前从 Angular 自定义管道获取返回值