“JSX öğe türü '…' herhangi bir yapıya veya çağrı imzasına sahip değil” hatası ne anlama geliyor?


170

Bir kod yazdım:

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

Bir hata alıyorum:

JSX öğe türünde Elemherhangi bir yapı veya çağrı imzası yok

Bunun anlamı ne?

Yanıtlar:


209

Bu, yapıcılar ve örnekler arasındaki bir karışıklıktır .

React'te bir bileşen yazarken şunu unutmayın:

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

Bunu şu şekilde kullanırsınız:

return <Greeter whoToGreet='world' />;

Sen yok bu şekilde kullanın:

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

İlk örnekte, etrafında geçiyoruz Greeter, yapıcı işlevini bizim bileşeni için. Doğru kullanım budur. İkinci örnekte, bir çevrede geçiyoruz örneği arasında Greeter. Bu yanlıştır ve çalışma zamanında "Nesne bir işlev değildir" gibi bir hatayla başarısız olur.


Bu kodla ilgili sorun

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

bir bekliyor olmasıdır örneği arasında React.Component. İstediğin götüren bir fonksiyonudur bir kurucu için React.Component:

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

veya benzer şekilde:

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

35
Bu yazı itibariyle, @types/reactbunları kullanıyorsanız , kullanımı en kolay yoldurfunction RenderGreeting(Elem: React.ComponentType) { ... }
Jthorpe

Merak ediyorum, function renderGreeting(Elem: typeof React.Component)ES6'da nasıl yazacağız?
Bruce Sun

Teşekkürler. Devletsiz bir işlevsel bileşeni geçirmek istersek durum ne olur? Sanırım function renderGreeting (Elem: new() => React.SFC<any>){...}öyleyse neden SFC türlerini şu şekilde açıklıyoruz: const Hello:React.SFC<any> = (props) => <div>Hello World</div>ve değil:const Hello: new() =>React.SFC<any> = (props) => <div>Hello World</div>
Ben Carp

1
@Jthorpe yorumunuz bir cevap olmalı ve o IMO'da kabul edilmiş olmalıdır.
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; }; "Özellik 'türü', 'typeof Bileşeni' türünde mevcut değil" hatası alıyorum.
Prakash P

62

Bir bileşen sınıfını parametre olarak almak istiyorsanız (bir örneğe karşı), şunu kullanın React.ComponentClass:

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

Şimdi karışımdaki işlevsel bileşenlerle React.ComponentType<any>, onları kapsamak için muhtemelen türü kullanmalısınız.
Zack,

34

JSX'ten TSX'e dönüştürdüğümde ve bazı kitaplıkları js / jsx olarak tutup diğerlerini ts / tsx'e dönüştürdüğümüzde, neredeyse her zaman TSX \ TS dosyalarındaki js / jsx içe aktarma deyimlerini değiştirmeyi unutuyorum.

import * as ComponentName from "ComponentName";

-e

import ComponentName from "ComponentName";

TSX'ten eski bir JSX (React.createClass) tarzı bileşeni çağırıyorsanız,

var ComponentName = require("ComponentName")


4
Sanırım tam tersini mi kastettin?
apieceofbart

5
TypeScript'i (ie in tsconfig.json) olarak yapılandırırsanız, inport ifadesinin değiştirilmesi gerekmez allowSyntheticDefaultImports. Bakın: typescriptlang.org/docs/handbook/compiler-options.html ve burada tartışma: blog.jonasbandi.net/2016/10/…
jbandi

12

Sahne aksesuarlarını gerçekten önemsemiyorsanız, mümkün olan en geniş türdür React.ReactType.

Bu, yerel dom öğelerinin dizge olarak aktarılmasına izin verir. React.ReactTypetüm bunları kapsar:

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


8

Material -ui kullanıyorsanız , TypeScript tarafından altı çizilen bileşenin tür tanımına gidin. Büyük ihtimalle böyle bir şey göreceksiniz

export { default } from './ComponentName';

Hatayı çözmek için 2 seçeneğiniz var:

1. JSX'de .defaultbileşeni kullanırken ekleyin:

import ComponentName from './ComponentName'

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

2. İçe aktarılırken "varsayılan" olarak dışa aktarılan bileşeni yeniden adlandırın:

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

const Component = () => <ComponentName />

Bu şekilde .default, bileşeni her kullandığınızda belirtmeniz gerekmez .


1
Bu, sorunumu çözmeme yardımcı oldu.
WhiteWalker

3

@Jthorpe değinildiği gibi, ComponentClasssadece ya izin verir Componentveya PureComponentancak bir FunctionComponent.

Eğer a geçmeye çalışırsanız FunctionComponent, typcript ... benzeri bir hata verecektir.

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

Ancak kullanarak ComponentTypeziyade ComponentClassher iki durum için izin verir. React bildirim dosyası başına tür şu şekilde tanımlanır ...

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

3

React Class bileşenini bildirirken, React.ComponentClass bunun yerine kullanın React.Component, ts hatasını düzeltir.


2

Benim durumumda, React.ReactNodetür yerine işlevsel bir bileşen için bir React.FCtür kullanıyordum.

Bu bileşende tam olarak:

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


2

Benim durumumda newtür tanımının içinde eksiktim.

some-js-component.d.ts dosya:

import * as React from "react";

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

ve tsxtürlenmemiş bileşeni içe aktarmaya çalıştığım dosyanın içinde :

import SomeJSXComponent from 'some-js-component'

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

1

Kullanabilirsiniz

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

Ancak, aşağıdakiler çalışıyor mu?

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

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

0

Bileşeni dışa aktarmadan önce Type Assertions'ı kullanarak çözdüm . TypeScript, redux 'compose' kullanarak oluşturduktan sonra tanımlayamadı, bu nedenle sahne türlerini IParentProps ve IProps'a böldüm ve Type Assertions yaparken IParentProps'ı kullandım

import { compose } from 'react-redux'
import HOC1 from 'HOCs/HOC1'
import HOC2 from 'HOCs/HOC2'

type IParentProps = {}
type IProps = {}

const Component: React.FC<IProps & IParentProps> = React.memo((props) => {

      return <SomeComponent {...props}/>

})

return compose(HOC1,HOC2)(Component) as React.FunctionComponent<IParentProps>

0

Fonksiyonel bileşeni herhangi bir bileşene destek olarak aktarıyorsanız, aşağıdakileri kullanın:

import React from 'react';

type RenderGreetingProps = {
  element: React.FunctionComponent<any>
};

function RenderGreeting(props: RenderGreetingProps) {
  const {element: Element} = props;

  return <span>Hello, <Element />!</span>;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.