javascript - Kontrollera om en komponent är en instans av React.ReactElement<any> i en barnkarta


Jag har en komponent som loopar igenom barn och omsluter dem i en div. Jag försöker lägga till ett undantag för det, men stöter på ett problem där jag inte kan kontrollera om barnet är ett ReactElement eller inte (React.ReactChild kan vara en sträng eller ett nummer, så det kanske inte har en typ).

När jag provar metoden nedan får jag: "'ReactElement' refererar endast till en typ, men används här som ett värde." samt "Egenskapen 'type' finns inte på typen 'ReactChild'."

All hjälp som pekar mig i rätt riktning skulle vara mycket uppskattad.

  {React.Children.map(children, (child: React.ReactChild) => {
        /**
         * Exclude these components from being
         * wrapped by the item wrapper.
         */
        if (child instanceof React.ReactElement<any> && child.type === Divider) {
          return child;
        }

        if (child) {
          return <div className="l-spacer__item">{React.cloneElement(child as React.ReactElement<any>)}</div>;
        }

        return null;
      })}

Svar #1

Du bör använda React.isValidElement. För ditt fall ovan:

        if (React.isValidElement(child) && child.type === Divider) {
          return child;
        }

Svar #2

child instanceof React.ReactElement<any>

är ogiltig eftersom React.ReactElement inte är ett värde. Det är ett gränssnitt. Gränssnitt är bara typer, och till skillnad från klasser har de inget motsvarande värde. Alla typer raderas. De har ingen körningstidrepresentation.

Dessutom används JavaScripts instanceof och bör förstås på följande sätt

value instanceof anotherValue

Detta förvirrar människor som kommer från syntaktiskt liknande språk med liknande namngivna operatorer men där högerledets operand är en typ. I JavaScript är båda operanderna alltid värden.

För att utföra din specifika kontroll, justera din kod till något i stil med

if (typeof child !== 'string' && typeof child !== 'number' && child.type === Divider) {
  return child;
}

Detta fungerar eftersom typen React.ReactChild definieras som

React.ReactElement | React.ReactText;

och React.ReactText definieras som

string | number

Genom att eliminera de fallen vet språket att det matchar det tredje möjliga unionsfallet, React.ReactElement, som har en type-egenskap.

Relaterade artiklar