ข้อผิดพลาด“ ประเภทองค์ประกอบ JSX '…' ไม่มีโครงสร้างใด ๆ หรือลายเซ็นการโทร” หมายความว่าอย่างไร


158

ฉันเขียนรหัสบางส่วน:

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

ฉันได้รับข้อผิดพลาด:

ประเภทองค์ประกอบ JSX Elemไม่มีการสร้างหรือลายเซ็นการโทรใด ๆ

มันหมายความว่าอะไร?

คำตอบ:


196

นี่คือความสับสนระหว่างการก่อสร้างและอินสแตนซ์

จำไว้ว่าเมื่อคุณเขียนองค์ประกอบใน React:

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

คุณใช้วิธีนี้:

return <Greeter whoToGreet='world' />;

คุณไม่ได้ใช้วิธีนี้:

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

ในตัวอย่างแรกเราผ่านไปGreeterแล้วฟังก์ชันตัวสร้างสำหรับส่วนประกอบของเรา นั่นคือการใช้งานที่ถูกต้อง ในตัวอย่างที่สองเราจะผ่านรอบตัวอย่างGreeterของ ไม่ถูกต้องและจะล้มเหลวขณะทำงานโดยมีข้อผิดพลาดเช่น "Object is not a function"


ปัญหาเกี่ยวกับรหัสนี้

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

คือว่ามันคาดหวังว่าอินสแตนซ์React.Componentของ สิ่งที่คุณต้องการฟังก์ชั่นที่ใช้ตัวสร้างสำหรับReact.Component:

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

หรือในทำนองเดียวกัน:

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

31
ตามที่เขียนไว้นี้หากคุณกำลังใช้งานอยู่@types/reactมันง่ายที่สุดที่จะใช้function RenderGreeting(Elem: React.ComponentType) { ... }
Jthorpe

แค่อยากรู้เราจะเขียนfunction renderGreeting(Elem: typeof React.Component)ใน ES6 อย่างไร
บรูซซัน

ขอบคุณ จะเป็นเช่นไรหากเราต้องการส่งผ่านส่วนประกอบการทำงานที่ไร้สัญชาติ? ฉันเดาว่าfunction renderGreeting (Elem: new() => React.SFC<any>){...}ถ้าอย่างนั้นทำไมเราถึงประกาศประเภทของ SFCs แบบนี้: const Hello:React.SFC<any> = (props) => <div>Hello World</div>และไม่ใช่:const Hello: new() =>React.SFC<any> = (props) => <div>Hello World</div>
Ben Carp

1
@Jthorpe ความคิดเห็นของคุณควรมีคำตอบและเป็นที่ยอมรับใน IMO นั้น
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; }; ฉันได้รับข้อผิดพลาด "Property" type "ไม่มีอยู่ในประเภท" typeof Component ""
Prakash P

60

หากคุณต้องการใช้คลาสองค์ประกอบเป็นพารามิเตอร์ (เทียบกับอินสแตนซ์) ให้ใช้React.ComponentClass:

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

ขณะนี้มีส่วนประกอบที่ใช้งานได้ในการผสมคุณอาจจะใช้React.ComponentType<any>ประเภทแทนที่จะรวมพวกเขา
แซค

34

เมื่อฉันแปลงจาก JSX เป็น TSX และเราเก็บบางไลบรารีเป็น js / jsx และแปลงอื่น ๆ เป็น ts / tsx ฉันเกือบลืมเปลี่ยน js / jsx คำสั่งการนำเข้าในไฟล์ TSX \ TS

import * as ComponentName from "ComponentName";

ถึง

import ComponentName from "ComponentName";

หากเรียกคอมโพเนนต์สไตล์ JSX (React.createClass) เก่าจาก TSX ให้ใช้

var ComponentName = require("ComponentName")


4
ฉันคิดว่าคุณหมายถึงวิธีอื่น ๆ ?
apieceofbart

5
การเปลี่ยนคำสั่ง inport จะไม่จำเป็นถ้าคุณกำหนดค่า typescript (เช่นในtsconfig.json) allowSyntheticDefaultImportsไป ดู: typescriptlang.org/docs/handbook/compiler-options.html และการอภิปรายที่นี่: blog.jonasbandi.net/2016/10/30
jbandi

11

React.ReactTypeจริงๆถ้าคุณไม่สนใจเกี่ยวกับอุปกรณ์ประกอบฉากแล้วประเภทที่กว้างที่สุดคือ

สิ่งนี้จะช่วยให้ผ่านองค์ประกอบ dom พื้นเมืองเป็นสตริง React.ReactTypeครอบคลุมสิ่งเหล่านี้ทั้งหมด:

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

8

หากคุณใช้material-uiให้ไปที่นิยามประเภทของส่วนประกอบซึ่งถูกขีดเส้นใต้โดย TypeScript เป็นไปได้มากที่คุณจะเห็นอะไรเช่นนี้

export { default } from './ComponentName';

คุณมี 2 ตัวเลือกในการแก้ไขข้อผิดพลาด:

1. เพิ่ม.defaultเมื่อใช้ส่วนประกอบใน JSX:

import ComponentName from './ComponentName'

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

2. เปลี่ยนชื่อองค์ประกอบซึ่งจะถูกส่งออกเป็น "ค่าเริ่มต้น" เมื่อนำเข้า:

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

const Component = () => <ComponentName />

วิธีนี้คุณไม่จำเป็นต้องระบุ.defaultทุกครั้งที่คุณใช้ส่วนประกอบ


1
สิ่งนี้ช่วยฉันในการแก้ไขปัญหาของฉัน
WhiteWalker

7

การทำงานต่อไปนี้สำหรับฉัน: https://github.com/microsoft/TypeScript/issues/28631#issuecomment-472606019ฉันแก้ไขได้โดยทำสิ่งนี้:

const Component = (isFoo ? FooComponent : BarComponent) as React.ElementType

ขอบคุณมันช่วยฉันได้มาก <3
AmerllicA

แต่ทำไมมันถึงใช้งานได้?
WebBrother

2

ในกรณีของฉันฉันใช้React.ReactNodeเป็นชนิดสำหรับส่วนประกอบที่ใช้งานได้แทนที่จะเป็นReact.FCชนิด

ในส่วนนี้จะต้องแน่นอน:

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

ในฐานะที่เป็น @Jthorpe พาดพิงถึง, ComponentClassเพียง แต่ช่วยให้อย่างใดอย่างหนึ่งComponentหรือแต่ไม่ได้เป็นPureComponentFunctionComponent

หากคุณพยายามที่จะผ่าน a FunctionComponent, typescript จะโยนข้อผิดพลาดคล้ายกับ ...

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

อย่างไรก็ตามโดยใช้ComponentTypeมากกว่าที่ComponentClassคุณอนุญาตสำหรับทั้งสองกรณี ตามไฟล์ประกาศการตอบสนองชนิดจะถูกกำหนดเป็น ...

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

2

ในกรณีของฉันฉันหายไปnewในการกำหนดประเภท

some-js-component.d.ts ไฟล์:

import * as React from "react";

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

และภายในtsxไฟล์ที่ฉันพยายามนำเข้าส่วนประกอบที่ไม่มีการพิมพ์:

import SomeJSXComponent from 'some-js-component'

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

2

เมื่อประกาศส่วนประกอบ React Class ให้ใช้React.ComponentClass แทนจากReact.Componentนั้นจะแก้ไขข้อผิดพลาด ts


1

คุณสามารถใช้ได้

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

อย่างไรก็ตามการทำงานต่อไปนี้เป็นอย่างไร

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

    return <span>Hello, <Elem {...propsToPass} />!</span>;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.