web-dev-qa-db-fra.com

Que signifie l'erreur "Le type d'élément JSX '...' n'a aucune signature de construction ou d'appel" signifie?

J'ai écrit du code:

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

Je reçois une erreur:

Le type d'élément JSX Elem n'a aucune signature de construction ou d'appel

Qu'est-ce que ça veut dire?

110
Ryan Cavanaugh

Ceci est une confusion entre constructeurs et instances.

Rappelez-vous que lorsque vous écrivez un composant dans React:

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

Vous l'utilisez de cette façon:

return <Greeter whoToGreet='world' />;

Vous ne pas l'utilisez de cette façon:

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

Dans le premier exemple, nous transmettons Greeter, le fonction constructeur pour notre composant. C'est l'utilisation correcte. Dans le deuxième exemple, nous passons autour d'une instance de Greeter. C'est incorrect et échouera au moment de l'exécution avec une erreur telle que "L'objet n'est pas une fonction".


Le problème avec ce code

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

c'est qu'il attend une instance de React.Component. Qu'est-ce que vous voulez une fonction qui prend n constructeur pour React.Component:

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

ou similaire:

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

Si vous voulez prendre une classe de composant en tant que paramètre (vs une instance), utilisez React.ComponentClass:

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

Lorsque je convertis de JSX en TSX et que nous conservons certaines bibliothèques au format js/jsx et en convertissons d’autres en ts/tsx, j’oublie presque toujours de modifier les instructions d’importation js/jsx dans les fichiers TSX\TS depuis

import * as ComponentName from "ComponentName";

à

import ComponentName from "ComponentName";

Si vous appelez un ancien composant de style JSX (React.createClass) depuis TSX, utilisez

var ComponentName = require("ComponentName")

27
Michael

Si vous ne vous souciez pas vraiment des accessoires, le type le plus large possible est React.ReactType.

Cela permettrait de passer des éléments dom natifs sous forme de chaîne. React.ReactType couvre tous ces domaines:

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

Si vous utilisez material-ui, accédez à la définition de type du composant, soulignée par TypeScript. Très probablement, vous verrez quelque chose comme ça

export { default } from './ComponentName';

Vous avez 2 options pour résoudre l'erreur:

1.Ajouter .default lors de l'utilisation du composant dans JSX:

import ComponentName from './ComponentName'

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

2.Remettez le nom du composant exporté en tant que "défaut" lors de l'importation:

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

const Component = () => <ComponentName />

Ainsi, vous n'avez pas besoin de spécifier .default à chaque fois que vous utilisez le composant.

3
Eduard