什么错误" JSX元素类型' ...'没有任何构造或呼叫签名"意思?

时间:2015-08-04 17:28:10

标签: reactjs typescript material-ui

我写了一些代码:

function renderGreeting(Elem: React.Component<any, any>) {
    return <span>Hello, <Elem />!</span>;
}

我收到错误:

  

JSX元素类型Elem没有任何构造或调用签名

这是什么意思?

16 个答案:

答案 0 :(得分:143)

这是构造函数实例之间的混淆。

请记住,在React中编写组件时:

class Greeter extends React.Component<any, any> {
    render() {
        return <div>Hello, {this.props.whoToGreet}</div>;
    }
}

你这样使用它:

return <Greeter whoToGreet='world' />;

没有以这种方式使用它:

let Greet = new Greeter();
return <Greet whoToGreet='world' />;

在第一个示例中,我们为组件传递了Greeter构造函数。这是正确的用法。在第二个示例中,我们传递了Greeter实例。这是不正确的,并且在运行时会因为错误而失败,例如&#34;对象不是函数&#34;。

此代码的问题

function renderGreeting(Elem: React.Component<any, any>) {
    return <span>Hello, <Elem />!</span>;
}

是它期待React.Component实例。你想要一个为React.Component带来构造函数的函数:

function renderGreeting(Elem: new() => React.Component<any, any>) {
    return <span>Hello, <Elem />!</span>;
}

或类似地:

function renderGreeting(Elem: typeof React.Component) {
    return <span>Hello, <Elem />!</span>;
}

答案 1 :(得分:48)

如果要将组件类作为参数(与实例对比),请使用React.ComponentClass

function renderGreeting(Elem: React.ComponentClass<any>) {
    return <span>Hello, <Elem />!</span>;
}

答案 2 :(得分:26)

当我从JSX转换为TSX并且我们将一些库保存为js / jsx并将其他库转换为ts / tsx时,我几乎总是忘记更改TSX \ TS文件中的js / jsx import语句

import * as ComponentName from "ComponentName";

import ComponentName from "ComponentName";

如果从TSX调用旧的JSX(React.createClass)样式组件,则使用

var ComponentName = require("ComponentName")

答案 3 :(得分:10)

以下内容对我有用:https://github.com/microsoft/TypeScript/issues/28631#issuecomment-472606019我通过执行以下操作对其进行了修复:

const Component = (isFoo ? FooComponent : BarComponent) as React.ElementType

答案 4 :(得分:7)

如果您真的不在乎道具,则可能的最大类型是React.ReactType

这将允许将本地dom元素作为字符串传递。 React.ReactType涵盖了所有这些内容:

renderGreeting('button');
renderGreeting(() => 'Hello, World!');
renderGreeting(class Foo extends React.Component {
   render() {
      return 'Hello, World!'
   }
});

答案 5 :(得分:4)

正如@Jthorpe所指,ComponentClass仅允许ComponentPureComponent,而不允许FunctionComponent

如果您尝试传递FunctionComponent,则打字稿将引发类似于...的错误。

Type '(props: myProps) => Element' provides no match for the signature 'new (props: myProps, context?: any): Component<myProps, any, any>'.

但是,通过使用ComponentType而不是ComponentClass,您可以允许两种情况。根据react声明文件,类型定义为...

type ComponentType<P = {}> = ComponentClass<P, any> | FunctionComponent<P>

答案 6 :(得分:4)

这是我搜索错误时的第一个结果,所以我想分享我在特定情况下的解决方案:

我使用的库如下所示:

export { default as Arc } from './shapes/Arc';

我错误地导入它,导致错误:

import Arc from "@visx/shape";

应该是什么

import { Arc } from "@visx/shape";

答案 7 :(得分:3)

如果要将功能组件作为道具传递给其他组件,请使用以下命令:

import React from 'react';

type RenderGreetingProps = {
  element: React.FunctionComponent<any>
};

function RenderGreeting(props: RenderGreetingProps) {
  const {element: Element} = props;

  return <span>Hello, <Element />!</span>;
}

答案 8 :(得分:2)

如果您使用的是 material-ui ,请转到该组件的类型定义,该类型定义由TypeScript加上下划线。您很有可能会看到类似这样的内容

export { default } from './ComponentName';

您有2个解决错误的方法:

1。在JSX中使用组件时添加.default

import ComponentName from './ComponentName'

const Component = () => <ComponentName.default />

2。导入时,重命名要作为“默认”导出的组件:

import { default as ComponentName } from './ComponentName'

const Component = () => <ComponentName />

这样,您无需在每次使用组件时都指定.default

答案 9 :(得分:1)

就我而言,我在类型定义内缺少new

some-js-component.d.ts文件:

import * as React from "react";

export default class SomeJSXComponent extends React.Component<any, any> {
    new (props: any, context?: any)
}

并在我尝试导入无类型组件的tsx文件中:

import SomeJSXComponent from 'some-js-component'

...inside render()
   return (
        <React.Fragment>
            <SomeJSXComponent withProps={asdf} />
        </React.Fragment>
   );

答案 10 :(得分:1)

您可以使用

function renderGreeting(props: {Elem: React.Component<any, any>}) {
    return <span>Hello, {props.Elem}!</span>;
}

但是,以下工作有效吗?

function renderGreeting(Elem: React.ComponentType) {
    const propsToPass = {one: 1, two: 2};

    return <span>Hello, <Elem {...propsToPass} />!</span>;
}

答案 11 :(得分:0)

在声明React类组件时,使用React.ComponentClass代替React.Component,它将解决ts错误。

答案 12 :(得分:0)

就我而言,我使用React.ReactNode作为功能组件的类型,而不是React.FC类型。

确切地说,在此组件中:

export const PropertiesList: React.FC = (props: any) => {
  const list:string[] = [
    ' Consequat Phasellus sollicitudin.',
    ' Consequat Phasellus sollicitudin.',
    '...'
  ]

  return (
    <List
      header={<ListHeader heading="Properties List" />}
      dataSource={list}
        renderItem={(listItem, index) =>
          <List.Item key={index}> {listItem } </List.Item>
      }
    />
  )
}

答案 13 :(得分:0)

我在导出组件之前通过使用 类型断言 解决了该问题。 TypeScript在使用redux'compose'进行组合后无法识别,因此我将道具类型分为IParentProps和IProps,并在进行类型断言时使用 IParentProps

import { compose } from 'react-redux'
import HOC1 from 'HOCs/HOC1'
import HOC2 from 'HOCs/HOC2'

type IParentProps = {}
type IProps = {}

const Component: React.FC<IProps & IParentProps> = React.memo((props) => {

      return <SomeComponent {...props}/>

})

return compose(HOC1,HOC2)(Component) as React.FunctionComponent<IParentProps>

答案 14 :(得分:0)

这是因为语法

以下是使用 TSX 的示例:

const SomeMadeComponent = () => (
    <div>
      <p>Some text</p>
    </div>
  );

您可以像使用普通组件一样使用它:

<SomeMadeComponent />

答案 15 :(得分:0)

看起来现在有一个特殊的新 TypeScript 类型来解决这个问题的需要:JSXElementConstructor。如果您让某人将构造函数传递给未知的 ReactElement 而不是该 ReactElement 的实例,则这是要传递的正确类型。

const renderGreeting = (Elem: JSXElementConstructor<any, any>) => {
    return <span>Hello, <Elem />!</span>;
}

这相当于上面选择的正确答案,因为使用 <Elem /> 相当于使用 new 关键字调用 JSX 元素的构造函数。