错误“ JSX元素类型'...'没有任何构造或调用签名”是什么意思?


Answers:


196

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

请记住,在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。这是不正确的,并且将在运行时失败,并显示诸如“对象不是函数”之类的错误。


此代码的问题

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>;
}

31
在撰写本文时,如果您正在使用@types/react它们,则最容易使用function RenderGreeting(Elem: React.ComponentType) { ... }
Jthorpe18年

只是好奇,我们如何function renderGreeting(Elem: typeof React.Component)用ES6 编写?
布鲁斯·孙

谢谢。如果我们要传递无状态功能组件,情况会怎样?我猜function renderGreeting (Elem: new() => React.SFC<any>){...}如果是这样,我们为什么要这样声明SFC的类型const Hello:React.SFC<any> = (props) => <div>Hello World</div>,而不是:const Hello: new() =>React.SFC<any> = (props) => <div>Hello World</div>
Ben Carp

1
@Jthorpe,您的评论应该是该IMO的答案和被接受的答案。
托马什Hübelbauer

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组件'上不存在属性'类型'”。
Prakash P

60

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

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

现在混合了功能组件,您可能应该改用React.ComponentType<any>类型来包含它们。
扎克

34

当我从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")


4
我想你的意思是相反的吗?
apieceofbart

5
如果将TypeScript(即in tsconfig.json)配置为,则不需要更改inport语句allowSyntheticDefaultImports。请参阅:typescriptlang.org/docs/handbook/compiler-options.html 和这里的讨论:blog.jonasbandi.net/2016/10/...
jbandi

11

如果您真的不关心道具,则可能是最广泛的类型React.ReactType

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

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

8

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

export { default } from './ComponentName';

您有2个选项可解决该错误:

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

import ComponentName from './ComponentName'

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

2.重命名在导入时要导出为“默认”的组件:

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

const Component = () => <ComponentName />

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


1
这有助于我解决问题。
WhiteWalker


2

就我而言,我使用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>
      }
    />
  )
}


2

正如@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>

2

就我而言,我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'

const NewComp = ({ asdf }: NewProps) => <SomeJSXComponent withProps={asdf} />

2

声明React Class组件时,请使用React.ComponentClass 而不是,React.Component它将修复ts错误。


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>;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.