TypeScript 3:JSX 元素类型“组件”没有任何构造或调用签名。 [2604]
Posted
技术标签:
【中文标题】TypeScript 3:JSX 元素类型“组件”没有任何构造或调用签名。 [2604]【英文标题】:TypeScript 3: JSX element type 'Component' does not have any construct or call signatures. [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。
【问题讨论】:
【参考方案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】:
我遇到过几次。试试这些:
-
将您的
PrivateRoute
输入为React.FC<Props>
将传入的组件键入为React.ElementType
关于 React 类型的终极真相来自the docs
编辑:React.ReactType(已弃用)-> React.ElementType
【讨论】:
#2 为我工作。现在是时候进行一些研究并弄清楚它为什么起作用了。也感谢您提供文档链接。export const BackNavigationTextWrapper = (WrappedComponent: typeof React.Component) => const BackNavigationTextWrappedComponent = (props, commonElements = : any) => return <WrappedComponent ...props backLabel=commonElements.backLabel || 'Go back to reservation details' /> ; 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 & 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) =>
...
【讨论】:
以上是关于TypeScript 3:JSX 元素类型“组件”没有任何构造或调用签名。 [2604]的主要内容,如果未能解决你的问题,请参考以下文章
TypeScript、react-router 和 jsx:JSX 元素类型 'Route' 没有任何构造或调用签名