reactjs - Vad är typen på 'children'-egenskapen?


Jag har en mycket enkel funktionell komponent enligt följande:

import * as React from 'react';

export interface AuxProps  { 
    children: React.ReactNode
 }


const aux = (props: AuxProps) => props.children;

export default aux;

Och en annan komponent:

import * as React from "react";

export interface LayoutProps  { 
   children: React.ReactNode
}

const layout = (props: LayoutProps) => (
    <Aux>
        <div>Toolbar, SideDrawer, Backdrop</div>
        <main>
            {props.children}
        </main>
    <Aux/>
);

export default layout;

Jag fortsätter att få följande felmeddelande:

[ts] JSX-elementtypen 'ReactNode' är inte en konstruktionsfunktion för JSX-element. Typen 'undefined' kan inte tilldelas typen 'ElementClass'. [2605]

Hur skriver jag detta korrekt?

Svar #1

Bara children: React.ReactNode.

Svar #2

För att använda <Aux> i din JSX, behöver det vara en funktion som returnerar ReactElement<any> | null. Det är definitionen av en funktionskomponent.

Men det är för närvarande definierat som en funktion som returnerar React.ReactNode, vilket är en mycket bredare typ. Som React-typningar säger:

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

Se till att de oönskade typerna neutraliseras genom att omsluta det returnerade värdet i en React Fragment (<></>):

const aux: React.FC<AuxProps> = props =>
  <>{props.children}</>;

Svar #3

Du kan också använda React.PropsWithChildren<P>.

type ComponentWithChildProps = React.PropsWithChildren<{example?: string}>;

Svar #4

Du kan använda ReactChildren och ReactChild:

import React, { ReactChildren, ReactChild } from 'react';
 
interface AuxProps {
  children: ReactChild | ReactChildren;
}

const Aux = ({ children }: AuxProps) => (<div>{children}</div>);

export default Aux;

Om du behöver skicka platta arrayer av element:

interface AuxProps {
  children: ReactChild | ReactChild[] | ReactChildren | ReactChildren[];
}

Svar #5

Det här är vad som fungerade för mig:

interface Props {
  children: JSX.Element[] | JSX.Element
}

Redigera Jag skulle rekommendera att använda children: React.ReactNode istället nu.

Svar #6

En React Node är en av följande typer:

  • Boolean (som ignoreras)
  • null eller undefined (vilket ignoreras)
  • Number
  • String
  • Ett React-element (resultat av JSX)
  • En array av någon av ovanstående, möjligen en inbäddad

Svar #7

import { ReactNode, FC } from 'react'

type Props = { children: ReactNode }

const App: FC<Props> = ({children}) => (<div>{children}</div>)

Svar #8

Jag använder följande

type Props = { children: React.ReactNode };

const MyComponent: React.FC<Props> = ({children}) => {
  return (
    <div>
      { children }
    </div>
  );

export default MyComponent;

Svar #9

du kan deklarera din komponent så här:

const MyComponent: React.FunctionComponent = (props) => {
    return props.children;
}

Svar #10

Returntypen för funktionskomponenten är begränsad till JSXElement | null i TypeScript. Detta är en nuvarande typbegränsning, ren React tillåter fler returntyper.

Minimal demonstrationssnutt

Du kan antingen använda en typförsäkran eller Fragment som en lösning:

const Aux = (props: AuxProps) => <>props.children</>; 
const Aux2 = (props: AuxProps) => props.children as ReactElement; 

ReactNode

children: React.ReactNode kan vara suboptimalt, om målet är att ha starka typer för Aux.

Nästan allt kan tilldelas den nuvarande ReactNode-typen, vilket är ekvivalent med {} | undefined | null. En säkrare typ för ditt fall kan vara:

interface AuxProps {
  children: ReactElement | ReactElement[]
}

Exempel :

Eftersom Aux behöver React-element som children, råkade vi av misstag lägga till en string till den. Då skulle ovanstående lösning ge fel i motsats till ReactNode - ta en titt på de länkade playgrounds.

Typade children är också användbara för icke-JSX props, som en Render Prop-callback.

Svar #11

Det allmänna sättet att hitta vilken typ som helst är genom exempel. Skönheten med TypeScript är att du har tillgång till alla typer, så länge du har de korrekta @types/-filerna.

För att svara på detta själv tänkte jag just på en komponent som React använder som har children-prop. Det första som kom upp i mitt huvud? Vad sägs om en <div />?

Allt du behöver göra är att öppna VSCode och skapa en ny .tsx-fil i ett React-projekt med @types/react.

import React from 'react';

export default () => (
  <div children={'test'} />
);

Att hovra över children-prop visar dig typen. Och vad vet du -- Dess typ är ReactNode (ingen anledning till ReactNode[]).

Om du sedan klickar på typdefinitionen tar det dig direkt till definitionen av children som kommer från DOMAttributes-gränssnittet.

// node_modules/@types/react/index.d.ts
interface DOMAttributes<T> {
  children?: ReactNode;
  ...
}

Observera: Denna process bör användas för att hitta vilken okänd typ som helst! Alla finns där och väntar bara på att du ska hitta dem :)

Svar #12

Du kan också använda JSX.ElementChildrenAttribute

export default function Layout({children}: JSX.ElementChildrenAttribute) {
    return <div>
        {children}
    </div>
}

Relaterade artiklar