【问题标题】:TypeScript 3: JSX element type 'Component' does not have any construct or call signatures. [2604]TypeScript 3:JSX 元素类型“组件”没有任何构造或调用签名。 [2604]
【发布时间】:2019-04-26 10:28:54
【问题描述】:

我正在尝试将 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;
        }
      }}
    />
  );
};

但我收到此错误:

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

我已经阅读了很多关于这个问题的其他线程,但它们似乎都处理了针对特定组件实现出现的这个错误。我无法更改有问题的组件或以不同方式导入它(就像公认的答案通常建议的那样),因为它可能是 any 组件。

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

【问题讨论】:

    标签: javascript reactjs typescript jsx


    【解决方案1】:

    派对迟到了,"@types/react-router-dom": "^4.3.4""@types/react": "16.9.1",如果你使用的是 RouteProps,你可能会得到同样的错误。

    JSX 元素类型“组件”没有任何构造或调用签名。 [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;
    }
    

    只需检查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 }
                }}
              />
            )
          }
        />
      );
    }
    

    【讨论】:

    • 我一般不会写无用的“谢谢”cmets,但谢谢!我一直在深入挖掘,这是唯一提到条件性作为潜在问题的事情,它为我解决了这个问题。
    • 谢谢,这真的很有用!我没有意识到这一点:)
    • 这应该是公认的答案。无需将类型设置为React.ElementType
    【解决方案2】:

    我遇到过几次。试试这些:

    1. 将您的PrivateRoute 输入为React.FC&lt;Props&gt;
    2. 将传入的组件键入为React.ElementType

    关于 React 类型的终极真相来自the docs

    编辑:React.ReactType(已弃用)-> React.ElementType

    【讨论】:

    • #2 为我工作。现在是时候进行一些研究并弄清楚它为什么起作用了。也感谢您提供文档链接。
    • export const BackNavigationTextWrapper = (WrappedComponent: typeof React.Component) =&gt; { const BackNavigationTextWrappedComponent = (props, { commonElements = {} }: any) =&gt; { return &lt;WrappedComponent {...props} backLabel={commonElements.backLabel || 'Go back to reservation details'} /&gt; }; BackNavigationTextWrappedComponent.type = WrappedComponent.type; return BackNavigationTextWrappedComponent; }; 我收到错误消息“类型'typeof Component'上不存在属性'type'”。
    • 尝试了 React.ReactType 并且它可以工作,但它似乎已被弃用,因此当前合适的类型是 React.ElementType。 VS Code 中没有错误。
    【解决方案3】:

    晚会,但对我有用的是:

    interface PrivateRouteProps extends Omit<RouteProps, "component"> {
      component: React.ElementType;
      // any additional vars
    }
    
    PrivateRoute: React.FC<PrivateRouteProps> = ({
      component: Component,
      ...rest
    }) => {
    // render code
    }

    【讨论】:

    • IMO,这是最好的答案,因为这样可以防止在没有组件的情况下使用 PrivateRoute。
    【解决方案4】:

    【讨论】:

    • 非常适合我
    • 这对我来说非常有用,但我通过使组件可选来对其进行了一些修改。 type PrivateRouteProps = { component?: React.ElementType } &amp; RouteProps
    【解决方案5】:

    这已经晚了,但如果有人不想要一个解决方案而是一个解释,让我们用一个例子来讨论这个错误来演示它

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

    假设我们想创建一个动态支付表单,如果查询参数是 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/>
    }
    

    运行这个,我们得到

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

    会发生什么?

    什么是组件?

    • 返回 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>
    }
    

    因为 gateway 持有 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/>
    }
    

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

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

    【讨论】:

    • 我根本没有遵循这个。您的示例与原始问题不同,因此我不知道如何关联。哪一行返回错误?
    【解决方案6】:

    我可以通过如下输入我的组件来解决错误:

    ...
    export function withApollo (PageComponent: () => JSX.Element) {
    const WithApollo = <T extends object>(props: T) => {
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-27
      • 2021-07-10
      • 2021-11-30
      • 2016-10-07
      • 2019-06-06
      • 2016-03-05
      • 2021-09-21
      • 2021-12-26
      相关资源
      最近更新 更多