Ho scritto del codice:
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
Ricevo un errore:
Il tipo di elemento JSX
Elem
non ha costrutti o firme di chiamata
Cosa significa?
Ho scritto del codice:
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
Ricevo un errore:
Il tipo di elemento JSX
Elem
non ha costrutti o firme di chiamata
Cosa significa?
Risposte:
Questa è una confusione tra costruttori ed istanze .
Ricorda che quando scrivi un componente in React:
class Greeter extends React.Component<any, any> {
render() {
return <div>Hello, {this.props.whoToGreet}</div>;
}
}
Lo usi in questo modo:
return <Greeter whoToGreet='world' />;
Non lo usi in questo modo:
let Greet = new Greeter();
return <Greet whoToGreet='world' />;
Nel primo esempio, stiamo passando in giro Greeter
, la funzione di costruzione per il nostro componente. Questo è l'uso corretto. Nel secondo esempio, stiamo passando a un'istanza di Greeter
. Non è corretto e non funzionerà in fase di esecuzione con un errore del tipo "L'oggetto non è una funzione".
Il problema con questo codice
function renderGreeting(Elem: React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
è che si aspetta un'istanza di React.Component
. Cosa vuoi una funzione che richiede un costruttore per React.Component
:
function renderGreeting(Elem: new() => React.Component<any, any>) {
return <span>Hello, <Elem />!</span>;
}
o similmente:
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>){...}
se sì perché dichiariamo il tipo di SFC come questo:, const Hello:React.SFC<any> = (props) => <div>Hello World</div>
e non: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; };
Ricevo un errore "Il tipo di proprietà" non esiste sul tipo "tipo di componente" ".
Se si desidera prendere una classe componente come parametro (rispetto a un'istanza), utilizzare React.ComponentClass
:
function renderGreeting(Elem: React.ComponentClass<any>) {
return <span>Hello, <Elem />!</span>;
}
React.ComponentType<any>
tipo invece di includerli.
Quando sto convertendo da JSX a TSX e manteniamo alcune librerie come js / jsx e ne convertiamo altre in ts / tsx quasi sempre dimentico di cambiare le istruzioni di importazione js / jsx nei file TSX \ TS da
import * as ComponentName from "ComponentName";
per
import ComponentName from "ComponentName";
Se si chiama un vecchio componente di stile JSX (React.createClass) da TSX, utilizzare
var ComponentName = require("ComponentName")
tsconfig.json
) su allowSyntheticDefaultImports
. Vedi: typescriptlang.org/docs/handbook/compiler-options.html e discussione qui: blog.jonasbandi.net/2016/10/10
Se davvero non ti importa degli oggetti di scena, allora il tipo più ampio possibile è React.ReactType
.
Ciò consentirebbe il passaggio di elementi dom nativi come stringa. React.ReactType
copre tutti questi:
renderGreeting('button');
renderGreeting(() => 'Hello, World!');
renderGreeting(class Foo extends React.Component {
render() {
return 'Hello, World!'
}
});
Se stai usando material-ui , vai alla definizione del tipo del componente, che è sottolineato da TypeScript. Molto probabilmente vedrai qualcosa del genere
export { default } from './ComponentName';
Hai 2 opzioni per risolvere l'errore:
1.Aggiungi .default
quando usi il componente in JSX:
import ComponentName from './ComponentName'
const Component = () => <ComponentName.default />
2. Rinominare il componente, che viene esportato come "predefinito", durante l'importazione:
import { default as ComponentName } from './ComponentName'
const Component = () => <ComponentName />
In questo modo non è necessario specificare .default
ogni volta che si utilizza il componente.
Il seguente ha funzionato per me: https://github.com/microsoft/TypeScript/issues/28631#issuecomment-472606019 Lo aggiusto facendo qualcosa del genere:
const Component = (isFoo ? FooComponent : BarComponent) as React.ElementType
Nel mio caso, stavo usando React.ReactNode
come tipo per un componente funzionale anziché React.FC
tipo.
In questo componente per l'esattezza:
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>
}
/>
)
}
Come accennato a @Jthorpe, ComponentClass
consente solo Component
o PureComponent
ma non a FunctionComponent
.
Se si tenta di passare un FunctionComponent
, dattiloscritto genererà un errore simile a ...
Type '(props: myProps) => Element' provides no match for the signature 'new (props: myProps, context?: any): Component<myProps, any, any>'.
Tuttavia, utilizzando ComponentType
piuttosto che ComponentClass
consentire per entrambi i casi. Per il file di dichiarazione di reazione il tipo è definito come ...
type ComponentType<P = {}> = ComponentClass<P, any> | FunctionComponent<P>
Nel mio caso mi mancava new
nella definizione del tipo.
some-js-component.d.ts
file:
import * as React from "react";
export default class SomeJSXComponent extends React.Component<any, any> {
new (props: any, context?: any)
}
e all'interno del tsx
file in cui stavo cercando di importare il componente non tipizzato:
import SomeJSXComponent from 'some-js-component'
const NewComp = ({ asdf }: NewProps) => <SomeJSXComponent withProps={asdf} />
Quando si dichiara il componente React Class, utilizzare React.ComponentClass
invece di React.Component
allora risolverà l'errore ts.
Puoi usare
function renderGreeting(props: {Elem: React.Component<any, any>}) {
return <span>Hello, {props.Elem}!</span>;
}
Tuttavia, funziona quanto segue?
function renderGreeting(Elem: React.ComponentType) {
const propsToPass = {one: 1, two: 2};
return <span>Hello, <Elem {...propsToPass} />!</span>;
}
@types/react
è più facile da usarefunction RenderGreeting(Elem: React.ComponentType) { ... }