Попытка динамического рендеринга тега JSX - PullRequest
1 голос
/ 28 апреля 2020

Я создаю <Text /> компонент, чтобы я мог легко контролировать использование текста в моем приложении. Я хочу иметь возможность выбрать тег для компонента <Text />, в зависимости от того, что это такое (например, <p> для основного текста, <h1> для заголовка).

Однако я ' Я застрял на первом шаге. Когда я пытаюсь использовать функцию для возврата тега, я получаю следующую ошибку:

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

Вот мой компонент:

import * as React from 'react'

export class Text extends React.Component {

  constructor(props) {
    super(props)
  }

  getMarkup() {
    return 'h1'
  }

  render() {
    const CustomTag = this.getMarkup()
    return (<CustomTag>Hello</CustomTag>)
  }

}

1 Ответ

3 голосов
/ 28 апреля 2020

Поскольку вы собираетесь рассматривать теги как строку, вы можете использовать React.createElement. Внутри render напишите следующее:

const element = React.createElement(this.getMarkup(), {}, 'Hello');
return <>{element}</>;

По сути, createElement ожидает тип элемента в виде строки, поэтому вы можете передать 'h1', не мешая при этом TypeScript.
Более того, вы можете видеть, что я передаю пустой массив в качестве второго аргумента: там вы можете передавать любые реквизиты, такие как style, onClick, ... Обычно в этом случае вы должны написать следующее:

const element = React.createElement(this.getMarkup(), {{...this.props}}, 'Hello');

Но, конечно, вам нужно будет добавить правильные типы в Text реквизит, используя React.HTMLProps<T> .. Примерно так:

class App extends React.Component<React.HTMLProps<HTMLHeadingElement | HTMLParagraphElement>, IState> {`

Где в этом случае я рассматриваю только h и p элементов.

РЕДАКТИРОВАТЬ: Если вы собираетесь объединить HTMLProps с вашими реквизитами, такими как IProps, то вы будете писать IProps & React.HTMLProps<HTMLHeadingElement | HTMLParagraphElement>.

В этот момент внутри this.props у вас будут (p | h) реквизиты И реквизиты, определенные внутри IProps.

Затем, в с этой точки зрения, поскольку элемент p и h не должен принимать реквизиты, поступающие с IProps, вам следует переписать createElement следующим образом:

// Assuming you have this IProps
interface IProps {
  tag: string;
  myProp: number;
}

// Inside render
const { tag, myProp, ...otherProps } = {...this.props};
const element = React.createElement(this.getMarkup(), otherProps, 'Hello');
return <>{element}</>;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...