jsx和React中的动态标签名称


162

我尝试编写一个React组件。对于html标题标签(h1,h2,h3等),其中标题优先级根据我们在道具中定义的优先级动态变化。

这是我尝试做的。

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

预期输出:

<h1>Hello</h1>

这是行不通的。有什么可能的方法可以做到这一点?


Answers:


328

无法就地执行此操作,只需将其放在变量中(首字母大写):

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

<CustomTag>Hello</CustomTag>

5
绝对比容易React.createClass,我更喜欢这种方式。谢谢。
Vadorequest'1

@zerkms您是否知道如何向CustomTag添加属性?谢谢
罗布

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

嗯 这是如何运作的?如果变量名是小写的,它只是将其插入为标签(例如,如果是customtag,我会得到<customtag> Hello </ customtag>)。这在任何地方都有记录吗?
Ibrahim

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元素。type参数可以是标签名称字符串(例如'div''span'),也可以是React组件类型(类或函数)。

用JSX编写的代码将转换为use React.createElement()React.createElement()如果您使用的是JSX,通常不会直接调用。请参阅React Without JSX了解更多信息。


11

如果您使用的是TypeScript,则会看到如下错误:

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

TypeScript不知道这CustomTag是一个有效的HTML标记名称,并抛出无用的错误。

要修复,请投射CustomTagkeyof JSX.IntrinsicElements

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

<CustomTag>Hello</CustomTag>

我在打字稿,但铸造它给出了这样的错误: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”或“ primary”,“ secondary”

标题组件:

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(上面由Felix提到)。

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

为了可组合性,道具和孩子都被传递。

参见示例

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.