Apa artinya kesalahan "jenis elemen JSX '...' tidak memiliki konstruk atau tanda tangan panggilan"?

158

Saya menulis beberapa kode:

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

Saya mendapatkan kesalahan:

Tipe elemen JSX Elemtidak memiliki tanda tangan konstruksi atau panggilan

Apa artinya?

Ryan Cavanaugh
sumber

Jawaban:

196

Ini adalah kebingungan antara konstruktor dan instance .

Ingat bahwa ketika Anda menulis komponen di Bereaksi:

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

Anda menggunakannya dengan cara ini:

return <Greeter whoToGreet='world' />;

Anda tidak menggunakannya dengan cara ini:

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

Dalam contoh pertama, kita sedang melewati Greeter, fungsi konstruktor untuk komponen kita. Itu penggunaan yang benar. Pada contoh kedua, kami membagikan turunan dari Greeter. Itu salah, dan akan gagal saat runtime dengan kesalahan seperti "Objek bukan fungsi".


Masalah dengan kode ini

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

adalah bahwa ia mengharapkan turunan dari React.Component. Apa yang Anda inginkan fungsi yang mengambil konstruktor untuk React.Component:

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

atau serupa:

function renderGreeting(Elem: typeof React.Component) {
    return <span>Hello, <Elem />!</span>;
}
Ryan Cavanaugh
sumber
31
Pada tulisan ini, jika Anda menggunakannya @types/reactpaling mudah digunakanfunction RenderGreeting(Elem: React.ComponentType) { ... }
Jthorpe
Hanya ingin tahu, bagaimana kita menulis function renderGreeting(Elem: typeof React.Component)dalam ES6?
Bruce Sun
Terima kasih. Apa yang akan terjadi jika kita ingin melewatkan komponen fungsional stateless? Saya kira function renderGreeting (Elem: new() => React.SFC<any>){...}Jika demikian mengapa kita menyatakan jenis SFC seperti ini:, const Hello:React.SFC<any> = (props) => <div>Hello World</div>dan tidak:const Hello: new() =>React.SFC<any> = (props) => <div>Hello World</div>
Ben Carp
1
@Jthorpe komentar Anda harus berupa jawaban dan yang diterima di IMO itu.
Tomáš 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; }; Saya mendapatkan kesalahan "Properti 'tipe' tidak ada pada tipe 'typeof Komponen'".
Prakash P
60

Jika Anda ingin mengambil kelas komponen sebagai parameter (vs contoh), gunakan React.ComponentClass:

function renderGreeting(Elem: React.ComponentClass<any>) {
    return <span>Hello, <Elem />!</span>;
}
Luke
sumber
Sekarang dengan komponen fungsional dalam campuran, Anda mungkin harus menggunakan React.ComponentType<any>jenisnya sebagai gantinya.
Zack
34

Ketika saya mengkonversi dari JSX ke TSX dan kami menyimpan beberapa perpustakaan sebagai js / jsx dan mengonversi yang lain ke ts / tsx, saya hampir selalu lupa untuk mengubah pernyataan impor js / jsx di file TSX \ TS dari

import * as ComponentName from "ComponentName";

untuk

import ComponentName from "ComponentName";

Jika memanggil komponen gaya JSX (React.createClass) tua dari TSX, maka gunakan

var ComponentName = require("ComponentName")

Michael
sumber
4
Saya pikir Anda bermaksud sebaliknya?
masing
5
Mengubah pernyataan inport tidak diperlukan jika Anda mengonfigurasi TypeScript (mis. In tsconfig.json) menjadi allowSyntheticDefaultImports. Lihat: typescriptlang.org/docs/handbook/compiler-options.html dan diskusi di sini: blog.jonasbandi.net/2016/10/...
jbandi
11

Jika Anda benar-benar tidak peduli dengan alat peraga maka jenis yang seluas mungkin adalah React.ReactType.

Ini akan memungkinkan lewat elemen dom asli sebagai string. React.ReactTypemencakup semua ini:

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

Jika Anda menggunakan material-ui , pergi ke ketik definisi komponen, yang digarisbawahi oleh TypeScript. Kemungkinan besar Anda akan melihat sesuatu seperti ini

export { default } from './ComponentName';

Anda memiliki 2 opsi untuk menyelesaikan kesalahan:

1.Tambahkan .defaultketika menggunakan komponen di JSX:

import ComponentName from './ComponentName'

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

2. Ganti nama komponen, yang diekspor sebagai "default", ketika mengimpor:

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

const Component = () => <ComponentName />

Dengan cara ini Anda tidak perlu menentukan .defaultsetiap kali Anda menggunakan komponen.

Eduard
sumber
1
Ini membantu saya dalam memperbaiki masalah saya.
WhiteWalker
2

Dalam kasus saya, saya menggunakan React.ReactNodesebagai tipe untuk komponen fungsional, bukan React.FCtipe.

Dalam komponen ini tepatnya:

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>
      }
    />
  )
}

ArchNoob
sumber
2

Sebagai @Jthorpe disinggung, ComponentClasshanya memungkinkan baik Componentatau PureComponenttapi bukan FunctionComponent.

Jika Anda mencoba untuk melewatkan FunctionComponent, naskah akan melontarkan kesalahan yang mirip dengan ...

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

Namun, dengan menggunakan ComponentTypedaripada yang ComponentClassAnda izinkan untuk kedua kasus. Per file deklarasi reaksi jenisnya didefinisikan sebagai ...

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

Dalam kasus saya, saya tidak ada newdi dalam definisi tipe.

some-js-component.d.ts mengajukan:

import * as React from "react";

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

dan di dalam tsxfile tempat saya mencoba mengimpor komponen yang tidak diketik:

import SomeJSXComponent from 'some-js-component'

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

Ketika mendeklarasikan komponen React Class, gunakan React.ComponentClass alih-alih React.Componentitu akan memperbaiki kesalahan ts.

snowyBunny
sumber
1

Kamu bisa memakai

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

Namun, apakah cara berikut ini berhasil?

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

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