动态JSX元素/标签名称

4
我想知道在ReactJS中动态呈现元素的最佳做法方法是什么。
考虑以下情况:
(1)参数工厂组件:一个参数化工厂组件的工作是根据字符串参数呈现组件,有没有一种方式可以不使用React.createElement实现呢?
<pre><code>// The following doesn't work
class Quiz extends React.Component{
  constructor (props){
    super (props);
    this.state = {
      questionText: '',
      correctAnswer: [],
      assetType: ['DragNDrop','MultipleChoice','MatchPairs']
    }
  }
  render(){
    const { questionText, correctAnswer } = this.state;
    return <{this.state.assetType[this.props.typeIndex] />;
  }
}
</code></pre>

(2)动态HTML标签:
根据整数输入呈现不同的HTML头标签。为此,我最初尝试使用模板字符串,但不得不采用条件渲染。

<pre><code>// No joy with Template strings
render (){
  <{`h${this.state.headerSize}`}>
    {this.state.headerText}
  </ {`h${this.state.headerSize}`}>
}

我喜欢使用JSX,在保持一致性方面,能够在JSX中使用动态元素名称将是很好的选择。

我也知道:

assetType: ['DragNDrop','MultipleChoice','MatchPairs']

可以存储为:

assetType: [<DragNDrop />,<MultipleChoice />, <MatchPairs />]

这个问题与JSX元素数组有关,如何将这些JSX元素存储在数据库中?我猜想我必须将它们存储为字符串,但是当从数据库中取回时如何使用它们呢?

有没有人可以提供任何可行的最佳实践方法来解决这些问题呢?

解决方案:

对于将JSX元素存储在数据库中的问题,您可以将它们转换为字符串并存储。然后,当您需要使用它们时,您可以使用React的dangerouslySetInnerHTML属性将其呈现为JSX元素。

这种方法不是最佳实践,因为它可能会导致潜在的安全漏洞。更好的方法是将数据存储为JSON格式,并在需要时将其转换为JSX元素。


headerSize'h1' 时,您可以执行 <this.state.headerSize>,您需要它是不完整的标签/整数吗? - Fabian Schultz
@FabianSchultz:真的吗?这对自定义的React元素也适用吗?上次我尝试时,出现了一个转译错误,导致我使用了下面答案中的一种解决方案... - Pineda
示例: http://jsbin.com/kiluwuv/edit?js,output - Fabian Schultz
@FabianSchultz:很酷,好知道。这似乎不适用于用户定义的React组件,即对于情况(1),我已定义了<DragNDrop/><MultipleChoice /><MatchPairs />,使用this.state.assetType [0]不会呈现<DragNDrop /> - Pineda
是的,你必须传递组件(对象)本身,而不是一个字符串。 - Fabian Schultz
感谢@FabianSchultz,我意识到这个问题实际上是一个重复的问题,所以我已经投票关闭它。 - Pineda
1个回答

7

关于动态HTML标签:

编辑:
正如文档所建议的那样,如果首先将动态类型分配给一个大写变量,则可以在运行时使用动态HTML标签:Dynamic types can be used at runtime

class Quiz extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            questionText: '',
            correctAnswer: [],
            assetType: ['DragNDrop', 'MultipleChoice', 'MatchPairs']
        }
    }
    render() {
        const <b>E</b>lementNameStartsWithCapitalLetter = this.state.assetType[0];
           // ^ -- capital letter here, ensure this works when used in JSX
        return <b><ElementNameStartsWithCapitalLetter /></b>;
    }
}

这是因为用户定义的JSX组件必须大写


之前的解决方案:

使用 React.createElement:

class Quiz extends React.Component{
  constructor (props){
    super (props);
    this.state = {
      questionText: '',
      correctAnswer: [],
      assetType: ['DragNDrop','MultipleChoice','MatchPairs']
    }
  }
  render(){
    const { questionText, correctAnswer } = this.state;
    {React.createElement(
      [this.props.typeIndex],
      {...questionText, ...correctAnswer}
    );}
  }
}

使用条件渲染:
// Conditional rendering works, but yuck!
// One condition per state works
// <b>but can be unnecessarily verbose</>
getHeader() {
  switch(this.state.headerSize){
    case 1:
      return <h1>{ this.state.headerText }; <h1>
    case 2:
      return <h2>{ this.state.headerText }<h2>
    .
    .
    .
    default:
      return null;
  }
}

render (){
  return { this.getHeader() }; // bound correctly in constructor of course :)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接