尝试动态呈现JSX标签

时间:2020-04-28 14:54:57

标签: javascript reactjs typescript jsx

我正在创建一个<Text />组件,以便可以轻松控制在应用程序中使用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 个答案:

答案 0 :(得分:3)

由于您将标签视为字符串,因此可以使用React.createElement。在render内,编写如下:

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

基本上,createElement期望元素的类型为字符串,因此您可以传递'h1'而不会使TypeScript困扰您。
此外,您可以看到我传递了一个空数组作为第二个参数:您可以传递诸如styleonClick,...之类的任何道具。通常,在这种情况下,您将编写如下: / p>

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

但是,当然,您需要使用TextReact.HTMLProps<T>道具中添加适当的类型。类似这样的东西:

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

在这种情况下,我只考虑hp元素。

编辑:如果您要将HTMLProps与自己的道具(例如IProps)结合使用,那么您将要编写IProps & React.HTMLProps<HTMLHeadingElement | HTMLParagraphElement>

这时,在this.props内部,您将拥有(p | h)道具和在IProps内部定义的道具。

然后,此时,由于ph元素不应该使用来自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}</>;