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?
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>;
}
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>;
}
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")
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!'
}
});
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.