Wie verwende ich Kinder mit React Stateless Functional Component in TypeScript?

85

Bei Verwendung von TypeScript mit React müssen wir nicht mehr erweitern React.Props, damit der Compiler weiß, dass alle Requisiten von React- Komponenten untergeordnete Elemente haben können:

interface MyProps { }

class MyComponent extends React.Component<MyProps, {}> {
  public render(): JSX.Element {
    return <div>{this.props.children}</div>;
  }
}

Bei zustandslosen Funktionskomponenten scheint dies jedoch nicht der Fall zu sein:

const MyStatelessComponent = (props: MyProps) => {
  return (
    <div>{props.children}</div>
  );
};

Gibt den Kompilierungsfehler aus:

Fehler: (102, 17) TS2339: Die Eigenschaft 'children' ist für den Typ 'MyProps' nicht vorhanden.

Ich denke, das liegt daran, dass der Compiler wirklich nicht wissen kann, dass childrenim Requisitenargument eine Vanillefunktion angegeben wird.

Die Frage ist also, wie wir Kinder in einer zustandslosen Funktionskomponente in TypeScript verwenden sollen.

Ich könnte zum alten Weg zurückkehren MyProps extends React.Props, aber die PropsBenutzeroberfläche ist als veraltet markiert , und zustandslose Komponenten haben oder unterstützen kein, Props.refwie ich es verstehe.

So konnte ich die childrenRequisite manuell definieren :

interface MyProps {
  children?: React.ReactNode;
}

Erstens: Ist ReactNodeder richtige Typ?

Zweitens: Ich muss Kinder als optional ( ?) schreiben, sonst denken die Verbraucher, dass childrendies ein Attribut der Komponente ( <MyStatelessComponent children={} />) sein soll, und lösen einen Fehler aus, wenn kein Wert angegeben wird.

Es scheint, als würde mir etwas fehlen. Kann jemand Klarheit darüber schaffen, ob mein letztes Beispiel die Verwendung zustandsloser Funktionskomponenten mit Kindern in React ist?

Aaron Beall
quelle

Antworten:

82

React 16.8 Update: Seit React 16.8 sind die Namen React.SFCund React.StatelessComponentveraltet. Tatsächlich sind sie zu Aliasnamen für React.FunctionComponentTyp oder React.FCkurz geworden.

Sie würden sie jedoch genauso verwenden:

const MyStatelessComponent : React.FunctionComponent<MyProps> = props =>
    <div>
        <p>{props.propInMyProps}</p>
        <p>{props.children}</p>
    </div>

Vor der Reaktion 16.8 (älter):

Im Moment können Sie den React.StatelessComponent<>Typ wie folgt verwenden :

const MyStatelessComponent : React.StatelessComponent<{}> = props =>
    <div>{props.children}</div>

Was ich dort hinzugefügt habe, ist das Setzen des Rückgabetyps der Komponente auf React.StatelessComponentTyp.

Für eine Komponente mit Ihren eigenen benutzerdefinierten Requisiten (wie MyPropsSchnittstelle):

const MyStatelessComponent : React.StatelessComponent<MyProps> = props =>
    <div>
        <p>{props.propInMyProps}</p>
        <p>{props.children}</p>
    </div>

Jetzt propshat die childrenEigenschaft sowie die von der MyPropsSchnittstelle.

Ich habe dies in Typoskript Version 2.0.7 überprüft

Darüber hinaus können Sie React.SFCanstelle der React.StatelessComponentKürze halber verwenden.

Leone
quelle
Vielen Dank! Es scheint, ich bin auf einer alten Version der Typisierungen, die dies nicht unterstützt ... Ich denke, es ist Zeit, die Kugel zu beißen und TS 2.0 mit@types
Aaron Beall
2
React.StatelessComponent/ React.SFCSind veraltet. Es wird empfohlen, React.FunctionComponentstattdessen darauf zu verweisen .
Alexander Kachkaev
Beachten Sie, dass diese Methode nicht funktioniert, wenn Sie eine generische Komponente haben
FunkeyFlo
93

Sie können React.PropsWithChildren<P>Typ für Ihre Requisiten verwenden:

interface MyProps { }

function MyComponent(props: React.PropsWithChildren<MyProps>) {
  return <div>{props.children}</div>;
}
Köder
quelle
0

Sie können verwenden

interface YourProps { }
const yourComponent: React.SFC<YourProps> = props => {}
Jun Yin
quelle
0

Einfachere Antwort: Verwenden Sie ReactNode:

interface MyProps {
  children?: React.ReactNode
}

Ob dies childrenoptional ist oder nicht (dh mit ?oder nicht), hängt von Ihrer Komponente ab. Das? ist die prägnanteste Art, das auszudrücken, also ist daran nichts auszusetzen.

Zur Geschichte: Dies war nicht unbedingt die richtige Antwort, als sie ursprünglich gefragt wurde: Der Typ ReactNodewurde (fast) in seiner aktuellen Form im März 2017 nur durch diese Pull-Anfrage hinzugefügt , aber fast jeder, der dies heute liest, sollte auf einer ausreichend modernen Version von React sein .

Zuletzt zum Übergeben childrenals "Attribut" (was in React lingo als "Requisite" und nicht als Attribut übergeben würde): Es ist möglich, liest sich aber in den meisten Fällen besser, wenn JSX-Kinder übergeben werden:

<MyComponent>
  <p>This is part of the children.</p>
</MyComponent>

liest sich leichter als

<MyComponent children={<p>This is part of the children.</p>} />
chris6953
quelle