TypeScript 3:JSX元素类型“ Component”没有任何构造或调用签名。[2604]

jac*_*les 5 javascript jsx typescript reactjs

我试图将类型为React.Component(或React.FunctionComponent)的变量传递给Route,如下所示:

import React from 'react';
import { Route } from 'react-router-dom';

type PrivateRouteProps = {
  component: React.Component | React.FunctionComponent;
  isAuthenticated: boolean;
  login: (...args: any[]) => any;
  path: string;
};

const PrivateRoute: React.FunctionComponent<PrivateRouteProps> = ({
  component: Component,
  isAuthenticated,
  login,
  path,
  ...rest
}) => {
  return (
    <Route
      path={path}
      {...rest}
      render={props => {
        if (isAuthenticated) {
          return <Component {...props} />;
        } else {
          login();
          return null;
        }
      }}
    />
  );
};
Run Code Online (Sandbox Code Playgroud)

但我收到此错误:

JSX元素类型“ Component”没有任何构造或调用签名。[2604]

我已经阅读了许多有关此问题的其他主题,但它们似乎都处理了针对特定组件实现的此错误。我不能更改有问题的组件或以不同的方式导入它(就像通常接受的答案一样),因为它可以是任何组件。

我正在使用TypeScript 3.1.6,Babel Core 7.1和React 16.6.3。

mat*_*ets 14

甚至后来参加聚会,但对我有用的是:

interface PrivateRouteProps extends Omit<RouteProps, "component"> {
  component: React.ElementType;
  // any additional vars
}

PrivateRoute: React.FC<PrivateRouteProps> = ({
  component: Component,
  ...rest
}) => {
// render code
}
Run Code Online (Sandbox Code Playgroud)


Yao*_*hen 8

晚了,使用"@types/react-router-dom": "^4.3.4""@types/react": "16.9.1",如果使用RouteProps,可能会遇到相同的错误。

JSX元素类型“ Component”没有任何构造或调用签名。[2604]

这是因为,在RouteProps接口中,component定义为,因此可能未定义。

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;
}
Run Code Online (Sandbox Code Playgroud)

只需检查是否component伪造即可解决。

function PrivateRoute({ component: Component, ...rest }: RouteProps) {
  if (!Component) return null;
  return (
    <Route
      {...rest}
      render={props =>
        fakeAuth.isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: props.location }
            }}
          />
        )
      }
    />
  );
}
Run Code Online (Sandbox Code Playgroud)

  • 我通常不会写无用的“谢谢”评论,但谢谢!我一直在深入挖掘,这是唯一提到条件性作为潜在问题的事情,它为我解决了它。 (4认同)

Eli*_*nen 7

我已经遇到过几次了。试试这些:

  1. 输入您PrivateRouteReact.SFC<Props>
  2. 输入您的传入组件为 React.ReactType

关于React类型的最终真理来自于文档

  • #2 对我有用。现在是时候做一些研究并弄清楚它到底为何有效。也感谢您提供文档链接。 (2认同)

Ahm*_*yed 5

这已经晚了,但万一有人不需要解决方案而是需要解释,让我们用一个示例来演示这个错误

function PaymentPage(){
  
   return <div>Payment Page</div>
}

Run Code Online (Sandbox Code Playgroud)

假设我们想要创建一个动态支付表单,如果查询参数是 with=stripe 那么我们假设他想用 stripe 支付,如果是 razorpay 我们假设它,...等等。

然后我们做类似的事情

function PaymentPage(){
   const router = useRouter;
   const {with_} = router.query;
   let GatewayComponent: Gateway | null = null;
   switch(with_){
     case 'stripe':
       GatewayComponent = <StripeGateway/>;
       break;
     case 'razorpay':
       GatewayComponent = <RazorpayGateway/>;
       break;
   }
   return <GatewayComponent/>
}
Run Code Online (Sandbox Code Playgroud)

运行这个,我们得到

JSX element type 'Component' does not have any construct or call signatures.
Run Code Online (Sandbox Code Playgroud)

会发生什么?

什么是组件?

  • 返回 JSX.Element 类型元素的构造函数

所以?

  • 我们没有返回构造函数,而是返回构造函数调用,这与假设它是构造函数相同GatewayComponent,但事实并非如此,它是一个保存 JSX 的变量

所以基本上,期望 x 是任何类型的构造函数,无论是函数还是类,如果它是函数,则该函数是渲染函数,如果它是类,则需要渲染方法。

回到我们的问题

function PaymentPage(){
   const router = useRouter;
   const {with_} = router.query;
   let gateway: Gateway | null = null;
   switch(with_){
     case 'stripe':
       gateway = <StripeGateway/>;
       break;
     case 'razorpay':
       gateway = <RazorpayGateway/>
       break;
   }
   return <React.Fragment> {gateway} </React.Fragment>
}
Run Code Online (Sandbox Code Playgroud)

因为网关保存的是 JSX,而不是返回 JSX 的构造函数

如果你想用它作为组件怎么办?

function PaymentPage(){
   const router = useRouter;
   const {with} = router.query;
   let GatewayComponent: Gateway | null = null;
   switch(with_){
     case 'stripe':
       return () => <StripeGateway/>
     case 'razorpay':
       return () => <RazorpayGateway/>
   }
   return <GatewayComponent/>
}
Run Code Online (Sandbox Code Playgroud)

现在它是一个构造函数,我们现在可以将它用作组件。

正式地,您传递构造函数而不是实例。