Ich habe Code geschrieben:
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
Ich erhalte eine Fehlermeldung:
Der JSX-Elementtyp
Elemhat keine Konstrukt- oder Aufrufsignaturen
Was heißt das?
Ich habe Code geschrieben:
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
Ich erhalte eine Fehlermeldung:
Der JSX-Elementtyp
Elemhat keine Konstrukt- oder Aufrufsignaturen
Was heißt das?
Antworten:
Dies ist eine Verwechslung zwischen Konstruktoren und Instanzen .
Denken Sie daran, wenn Sie eine Komponente in React schreiben:
class Greeter extends React.Component<any, any> {
render() {
return <div>Hello, {this.props.whoToGreet}</div>;
}
}
Sie verwenden es so:
return <Greeter whoToGreet='world' />;
Sie verwenden es nicht so:
let Greet = new Greeter();
return <Greet whoToGreet='world' />;
Im ersten Beispiel geben wir Greeterdie Konstruktorfunktion für unsere Komponente weiter. Das ist die richtige Verwendung. Im zweiten Beispiel geben wir eine Instanz von weiter Greeter. Das ist falsch und schlägt zur Laufzeit mit einem Fehler wie "Objekt ist keine Funktion" fehl.
Das Problem mit diesem Code
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
ist, dass es eine Instanz von erwartet React.Component. Was möchten Sie eine Funktion, die einen Konstruktor benötigt für React.Component:
function renderGreeting(Elem: new() => React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
oder ähnlich:
function renderGreeting(Elem: typeof React.Component) {
return <span>Hello, <Elem />!</span>;
}
function renderGreeting(Elem: typeof React.Component)in ES6?
function renderGreeting (Elem: new() => React.SFC<any>){...}wenn ja, warum deklarieren wir die Art der SFCs wie folgt: const Hello:React.SFC<any> = (props) => <div>Hello World</div>und nicht:const Hello: new() =>React.SFC<any> = (props) => <div>Hello World</div>
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; }; Ich erhalte die Fehlermeldung "Eigenschaft 'Typ' existiert nicht für Typ 'Typ der Komponente'".
Wenn Sie eine Komponentenklasse als Parameter (gegenüber einer Instanz) verwenden möchten, verwenden Sie React.ComponentClass:
function renderGreeting(Elem: React.ComponentClass<any>) {
return <span>Hello, <Elem />!</span>;
}
React.ComponentType<any>Typ verwenden, um sie einzuschließen.
Wenn ich von JSX nach TSX konvertiere und einige Bibliotheken als js / jsx behalten und andere nach ts / tsx konvertieren, vergesse ich fast immer, die Importanweisungen von js / jsx in den TSX \ TS-Dateien von zu ändern
import * as ComponentName from "ComponentName";
zu
import ComponentName from "ComponentName";
Wenn Sie eine alte JSX-Stilkomponente (React.createClass) von TSX aus aufrufen, verwenden Sie
var ComponentName = require("ComponentName")
tsconfig.json) auf konfigurieren allowSyntheticDefaultImports. Siehe: typescriptlang.org/docs/handbook/compiler-options.html und Diskussion hier: blog.jonasbandi.net/2016/10/…
Wenn Sie sich wirklich nicht für Requisiten interessieren, ist der größtmögliche Typ React.ReactType.
Dies würde die Übergabe nativer dom-Elemente als Zeichenfolge ermöglichen. React.ReactTypedeckt all dies ab:
renderGreeting('button');
renderGreeting(() => 'Hello, World!');
renderGreeting(class Foo extends React.Component {
render() {
return 'Hello, World!'
}
});
Wenn Sie material-ui verwenden , wechseln Sie zur Typdefinition der Komponente, die von TypeScript unterstrichen wird. Höchstwahrscheinlich werden Sie so etwas sehen
export { default } from './ComponentName';
Sie haben zwei Möglichkeiten, um den Fehler zu beheben:
1. Fügen Sie .defaultbei Verwendung der Komponente in JSX Folgendes hinzu :
import ComponentName from './ComponentName'
const Component = () => <ComponentName.default />
2.Benennen Sie die Komponente, die exportiert wird, beim Importieren als "Standard" um:
import { default as ComponentName } from './ComponentName'
const Component = () => <ComponentName />
Auf diese Weise müssen Sie nicht .defaultjedes Mal angeben, wenn Sie die Komponente verwenden.
Folgendes hat bei mir funktioniert: https://github.com/microsoft/TypeScript/issues/28631#issuecomment-472606019 Ich behebe das Problem, indem ich so etwas mache:
const Component = (isFoo ? FooComponent : BarComponent) as React.ElementType
Wenn Sie die React-Klassenkomponente deklarieren, verwenden Sie React.ComponentClass stattdessen React.Component, um den ts-Fehler zu beheben.
In meinem Fall habe ich React.ReactNodeanstelle eines React.FCTyps einen Typ für eine Funktionskomponente verwendet.
In dieser Komponente um genau zu sein:
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>
}
/>
)
}
Wie @Jthorpe angedeutet hat, ComponentClasserlaubt nur entweder Componentoder PureComponentaber nicht a FunctionComponent.
Wenn Sie versuchen, a zu übergeben FunctionComponent, gibt Typoskript einen Fehler aus, der ...
Type '(props: myProps) => Element' provides no match for the signature 'new (props: myProps, context?: any): Component<myProps, any, any>'.
Verwenden Sie jedoch beide Fälle , ComponentTypeanstatt ComponentClasssie zuzulassen. In der React-Deklarationsdatei ist der Typ definiert als ...
type ComponentType<P = {}> = ComponentClass<P, any> | FunctionComponent<P>
In meinem Fall fehlte ich newin der Typdefinition.
some-js-component.d.ts Datei:
import * as React from "react";
export default class SomeJSXComponent extends React.Component<any, any> {
new (props: any, context?: any)
}
und in der tsxDatei, in der ich versucht habe, die untypisierte Komponente zu importieren:
import SomeJSXComponent from 'some-js-component'
const NewComp = ({ asdf }: NewProps) => <SomeJSXComponent withProps={asdf} />
Sie können verwenden
function renderGreeting(props: {Elem: React.Component<any, any>}) {
return <span>Hello, {props.Elem}!</span>;
}
Funktioniert jedoch Folgendes?
function renderGreeting(Elem: React.ComponentType) {
const propsToPass = {one: 1, two: 2};
return <span>Hello, <Elem {...propsToPass} />!</span>;
}
@types/reactfunction RenderGreeting(Elem: React.ComponentType) { ... }