Dynamischer Tag-Name in jsx und React

162

Ich versuche eine React-Komponente zu schreiben. für HTML-Überschriften-Tags (h1, h2, h3 usw.), bei denen sich die Überschriftenpriorität basierend auf der in den Requisiten definierten Priorität dynamisch ändert.

Hier was ich versuche zu tun.

<h{this.props.priority}>Hello</h{this.props.priority}>

erwartete Ausgabe:

<h1>Hello</h1>

Das funktioniert nicht. Gibt es eine mögliche Methode, um dies zu tun?

Eranga Kapukotuwa
quelle
Mögliches Duplikat der Namen der dynamischen React / JSX-Komponenten
Jordan Running

Antworten:

328

Keine Möglichkeit, dies an Ort und Stelle zu tun, setzen Sie es einfach in eine Variable ( mit großgeschriebenem Anfangsbuchstaben ):

const CustomTag = `h${this.props.priority}`;

<CustomTag>Hello</CustomTag>
zerkms
quelle
5
Auf jeden Fall einfacher als React.createClass, ich bevorzuge diesen Weg. Vielen Dank.
Vadorequest
@zerkms Haben Sie eine Idee, wie Sie CustomTag Attribute hinzufügen können? danke
Sabrina Luo
1
@Sabrina<CustomTag foo="bar">
Zerkms
Huh. Wie funktioniert das? Wenn der Variablenname klein geschrieben ist, wird er nur als Tag eingefügt (z. B. wenn es sich um einen benutzerdefinierten Tag handelt, würde ich <customtag> Hallo </ customtag> erhalten). Ist das irgendwo dokumentiert?
Ibrahim
5
Wenn die Komponente in der Eigenschaft eines Objekts gespeichert ist, ist kein Großbuchstabe erforderlich. var foo = { bar: CustomTag }; return <foo.bar />funktioniert gut.
jdunning
29

Der Vollständigkeit halber können Sie, wenn Sie einen dynamischen Namen verwenden möchten, auch direkt aufrufen, React.createElementanstatt JSX zu verwenden:

React.createElement(`h${this.props.priority}`, null, 'Hello')

Dadurch muss keine neue Variable oder Komponente erstellt werden.

Mit Requisiten:

React.createElement(
  `h${this.props.priority}`,
  {
    foo: 'bar',
  },
  'Hello'
)

Aus den Dokumenten :

Erstellen Sie ein neues React-Element des angegebenen Typs und geben Sie es zurück. Das Typargument kann entweder eine Tag-Namenszeichenfolge (wie 'div'oder 'span') oder ein React-Komponententyp (eine Klasse oder eine Funktion) sein.

Mit JSX geschriebener Code wird zur Verwendung konvertiert React.createElement(). Sie werden normalerweise nicht React.createElement()direkt aufgerufen, wenn Sie JSX verwenden. Weitere Informationen finden Sie unter Reagieren ohne JSX .

Felix Kling
quelle
11

Wenn Sie TypeScript verwenden, wird ein Fehler wie der folgende angezeigt:

Type '{ children: string; }' has no properties in common with type 'IntrinsicAttributes'.ts(2559)

TypeScript weiß nicht, dass CustomTages sich um einen gültigen HTML-Tag-Namen handelt, und gibt einen nicht hilfreichen Fehler aus.

Zum Reparieren CustomTagals keyof JSX.IntrinsicElements!

const CustomTag = `h${this.props.priority}` as keyof JSX.IntrinsicElements;

<CustomTag>Hello</CustomTag>
Jack Steam
quelle
Ich bin auf TypeScript, aber das Casting gibt diesen Fehler:Types of property 'crossOrigin' are incompatible. Type 'string | undefined' is not assignable to type '"" | "anonymous" | "use-credentials" | undefined'. Type 'string' is not assignable to type '"" | "anonymous" | "use-credentials" | undefined'.
Can Poyrazoğlu
8

Alle anderen Antworten funktionieren gut, aber ich würde einige zusätzliche hinzufügen, weil auf diese Weise:

  1. Es ist ein bisschen sicherer. Selbst wenn Ihre Typprüfung fehlschlägt, geben Sie dennoch eine ordnungsgemäße Komponente zurück.
  2. Es ist deklarativer. Jeder, der sich diese Komponente ansieht, kann sehen, was sie zurückgeben könnte.
  3. Es ist zum Beispiel flexibler als 'h1', 'h2', ... für die Art Ihrer Überschrift können Sie einige andere abstrakte Konzepte haben: 'sm', 'lg' oder 'primary', 'Secondary'

Die Überschriftenkomponente:

import React from 'react';

const elements = {
  h1: 'h1',
  h2: 'h2',
  h3: 'h3',
  h4: 'h4',
  h5: 'h5',
  h6: 'h6',
};

function Heading({ type, children, ...props }) {    
  return React.createElement(
    elements[type] || elements.h1, 
    props, 
    children
  );
}

Heading.defaultProps = {
  type: 'h1',
};

export default Heading;

Welches können Sie es wie verwenden

<Heading type="h1">Some Heading</Heading>

oder Sie können ein anderes abstraktes Konzept haben, zum Beispiel können Sie eine Größe Requisiten definieren wie:

import React from 'react';

const elements = {
  xl: 'h1',
  lg: 'h2',
  rg: 'h3',
  sm: 'h4',
  xs: 'h5',
  xxs: 'h6',
};

function Heading({ size, children }) {
  return React.createElement(
    elements[size] || elements.rg, 
    props, 
    children
  );
}

Heading.defaultProps = {
  size: 'rg',
};

export default Heading;

Welches können Sie es wie verwenden

<Heading size="sm">Some Heading</Heading>
Saman Shafigh
quelle
2

Bei dynamischen Überschriften (h1, h2 ...) könnte eine Komponente wie React.createElementoben erwähnt (oben von Felix erwähnt ) zurückkehren.

const Heading = ({level, children, ...props}) => {
    return React.createElement(`h${level}`, props , children)
}

Aus Gründen der Kompositionsfähigkeit werden sowohl Requisiten als auch Kinder übergeben.

Siehe Beispiel

Robstarbuck
quelle