Nome tag dinamico in jsx e React


163

Provo a scrivere un componente React. per i tag di intestazione html (h1, h2, h3, ecc ...), in cui la priorità dell'intestazione cambia dinamicamente in base alla priorità che abbiamo definito nei puntelli.

Ecco cosa provo a fare.

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

uscita prevista:

<h1>Hello</h1>

Questo non funziona. Esiste un metodo possibile per farlo?


Risposte:


329

Non c'è modo di farlo sul posto, basta inserirlo in una variabile ( con la prima lettera maiuscola ):

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

<CustomTag>Hello</CustomTag>

5
Decisamente più facile di React.createClass, preferisco così. Grazie.
Vadorequest,

@zerkms Hai idea di come aggiungere attributi a CustomTag? grazie
Sabrina Luo,

1
@Sabrina<CustomTag foo="bar">
zerkms,

Huh. Come funziona? Se il nome della variabile è minuscolo, lo inserisce semplicemente come tag (ad es. Se fosse un tag personalizzato, otterrei <customtag> Ciao </customtag>). Questo è documentato ovunque?
Ibrahim,

5
Se il componente è archiviato nella proprietà di un oggetto, non è necessaria la prima lettera maiuscola. var foo = { bar: CustomTag }; return <foo.bar />funziona bene.
jdunning

29

Per completezza, se si desidera utilizzare un nome dinamico, è anche possibile chiamare direttamente React.createElementanziché utilizzare JSX:

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

Questo evita di dover creare una nuova variabile o componente.

Con oggetti di scena:

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

Dai documenti :

Crea e restituisce un nuovo elemento React del tipo specificato. L'argomento type può essere una stringa del nome tag (come 'div'o 'span') oppure un tipo di componente React (una classe o una funzione).

Il codice scritto con JSX verrà convertito in uso React.createElement(). In genere non si invocherà React.createElement()direttamente se si utilizza JSX. Vedi React Without JSX per saperne di più.


11

Se stai usando TypeScript, vedrai un errore come questo:

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

TypeScript non sa che CustomTagè un nome tag HTML valido e genera un errore inutile.

Per risolvere, lancia CustomTagcome keyof JSX.IntrinsicElements!

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

<CustomTag>Hello</CustomTag>

Sono su TypeScript ma il casting dà questo errore: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

Tutte le altre risposte stanno funzionando bene, ma vorrei aggiungere qualche extra, perché facendo questo:

  1. È un po 'più sicuro. Anche se la verifica del tipo non riesce, viene comunque restituito un componente appropriato.
  2. È più dichiarativo. Chiunque osservi questo componente può vedere cosa potrebbe restituire.
  3. È più flessibile, ad esempio, invece di 'h1', 'h2', ... per il tipo di Titolo puoi avere altri concetti astratti 'sm', 'lg' o 'primary', 'secondario'

Il componente Titolo:

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;

Che puoi usare come

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

oppure puoi avere un concetto astratto diverso, ad esempio puoi definire oggetti di dimensioni come:

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;

Che puoi usare come

<Heading size="sm">Some Heading</Heading>

2

Nell'istanza delle intestazioni dinamiche (h1, h2 ...) , un componente potrebbe restituire React.createElement(menzionato sopra da Felix ) in questo modo.

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

Per la componibilità, vengono passati sia oggetti di scena che bambini.

Vedi esempio

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.