Nombre de etiqueta dinámica en jsx y React


163

Intento escribir un componente Reaccionar. para etiquetas de encabezado html (h1, h2, h3, etc.), donde la prioridad del encabezado cambia dinámicamente en función de la prioridad que hemos definido en los accesorios.

Aquí lo que intento hacer.

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

Rendimiento esperado:

<h1>Hello</h1>

Esto no está funcionando. ¿Hay algún método posible para hacer esto?


Respuestas:


329

No hay forma de hacer eso en el lugar, simplemente póngalo en una variable ( con la primera letra en mayúscula ):

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

<CustomTag>Hello</CustomTag>

55
Definitivamente más fácil que React.createClass, prefiero de esta manera. Gracias.
Vadorequest

@zerkms ¿Tiene alguna idea de cómo agregar atributos a CustomTag? gracias
Sabrina Luo

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

Huh ¿Como funciona esto? Si el nombre de la variable está en minúscula, simplemente lo inserta como una etiqueta (por ejemplo, si fuera una etiqueta personalizada, obtendría <customtag> Hola </customtag>). ¿Está esto documentado en alguna parte?
Ibrahim

55
Si el componente se almacena en la propiedad de un objeto, no es necesaria una primera letra mayúscula. var foo = { bar: CustomTag }; return <foo.bar />funciona bien.
Jdunning

29

Para completar, si desea usar un nombre dinámico, también puede llamar directamente en React.createElementlugar de usar JSX:

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

Esto evita tener que crear una nueva variable o componente.

Con accesorios:

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

De los documentos :

Crea y devuelve un nuevo elemento React del tipo dado. El argumento de tipo puede ser una cadena de nombre de etiqueta (como 'div'o 'span') o un tipo de componente Reaccionar (una clase o una función).

El código escrito con JSX se convertirá para usar React.createElement(). Por lo general, no invocará React.createElement()directamente si está utilizando JSX. Consulte Reaccionar sin JSX para obtener más información.


11

Si está utilizando TypeScript, habrá visto un error como este:

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

TypeScript no sabe que CustomTages un nombre de etiqueta HTML válido y arroja un error inútil.

¡Para arreglar, lanzar CustomTagcomo keyof JSX.IntrinsicElements!

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

<CustomTag>Hello</CustomTag>

Estoy en TypeScript pero al 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'.
emitirlo aparece

8

Todas las otras respuestas están funcionando bien, pero agregaría un poco más, porque al hacer esto:

  1. Es un poco más seguro. Incluso si su verificación de tipo falla, aún devuelve un componente adecuado.
  2. Es más declarativo. Al mirar este componente, cualquiera puede ver lo que podría devolver.
  3. Es más flexible, por ejemplo, en lugar de 'h1', 'h2', ... para el tipo de título, puede tener otros conceptos abstractos 'sm', 'lg' o 'primario', 'secundario'

El componente de encabezado:

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;

Que puedes usar como

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

o puede tener un concepto abstracto diferente, por ejemplo, puede definir accesorios de tamaño como:

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;

Que puedes usar como

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

2

En el caso de los encabezados dinámicos (h1, h2 ...) , un componente podría regresar React.createElement(mencionado anteriormente por Felix ) así.

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

Para la compostibilidad, se pasan los accesorios y los niños.

Ver ejemplo

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.