Ім'я динамічного тегу в jsx та React


162

Я намагаюся написати компонент React. для тегів заголовка html (h1, h2, h3 тощо), де пріоритет заголовка динамічно змінюється на основі пріоритету, визначеного нами в реквізитах.

Ось що я намагаюся зробити.

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

очікуваний вихід:

<h1>Hello</h1>

Це не працює. Чи можливий спосіб зробити це?


Відповіді:


328

Нічого не робити цього на місці, просто покладіть його в змінну ( з першої літери з великої літери ):

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

<CustomTag>Hello</CustomTag>

5
Однозначно простіше, ніж React.createClassя віддаю перевагу саме цьому. Дякую.
Vadorequest

@zerkms Ви маєте ідею, як додати атрибути до CustomTag? дякую
Сабріна Лоо

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

Ага. Як це працює? Якщо ім'я змінної є малим, воно просто вставляє це як тег (наприклад, якби це був customtag, я отримав би <customtag> Hello </customtag>). Це десь задокументовано?
Ібрагім

5
Якщо компонент зберігається у властивості об'єкта, перша літера з великої літери не потрібна. var foo = { bar: CustomTag }; return <foo.bar />працює чудово.
jdunning

29

Для повноти, якщо ви хочете використовувати динамічне ім'я, ви можете також безпосередньо зателефонувати React.createElementзамість JSX:

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

Це дозволяє уникнути створення нової змінної чи компонента.

З реквізитом:

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

З документів :

Створіть і поверніть новий елемент React заданого типу. Аргументом типу може бути або рядок імені тега (наприклад, 'div'або 'span'), або тип компонента React (клас або функція).

Код, написаний JSX, буде перетворений у використання React.createElement(). Зазвичай React.createElement()ви не будете звертатися безпосередньо, якщо ви використовуєте JSX. Дивіться Реагувати без JSX, щоб дізнатися більше.


11

Якщо ви використовуєте TypeScript, ви побачили подібну помилку:

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

TypeScript не знає, що CustomTagце дійсне ім'я HTML-тегу, і видає непотрібну помилку.

Щоб виправити, відкиньте CustomTagяк keyof JSX.IntrinsicElements!

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

<CustomTag>Hello</CustomTag>

Я на TypeScript, але кастинг дає цю помилку: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'.
Може Poyrazoğlu

8

Усі інші відповіді спрацьовують нормально, але я хотів би додати кілька додаткових, тому що виконуючи це:

  1. Це трохи безпечніше. Навіть якщо перевірка типу не вдається, ви все одно повернете належний компонент.
  2. Це більш декларативно. Будь-хто, дивлячись на цей компонент, може побачити, що він може повернути.
  3. Він є більш гнучким, наприклад замість 'h1', 'h2', ... для типу заголовка у вас можуть бути деякі інші абстрактні поняття 'sm', 'lg' або 'basic', 'second'

Компонент заголовка:

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;

Який ти можеш так використовувати

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

або у вас може бути інше абстрактне поняття, наприклад ви можете визначити розмір реквізиту, наприклад:

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;

Який ти можеш так використовувати

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

2

У випадку динамічних заголовків (h1, h2 ...) компонент може повертатися React.createElement(згаданий вище Фелікс ) так.

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

Для компонування передаються і реквізити, і діти.

Див. Приклад

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.