【问题标题】:Dynamic JSX element/tag names动态 JSX 元素/标签名称
【发布时间】:2017-05-28 19:40:45
【问题描述】:

我只是想知道是否存在使用 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,如果能够使用动态元素名称来保持一致性,那就太好了。

我也知道:

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

可以存储为:

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

这会起作用。

我对 JSX 元素数组的一个问题是如何将这些 JSX 元素存储在数据库中?我猜我必须将它们存储为Strings,但是当从数据库中拉回时如何使用它们?

任何人都可以就这些问题提出任何可行的最佳实践方法吗?

【问题讨论】:

  • headerSize'h1' 时你可以做&lt;this.state.headerSize&gt;,你要求它是一个不完整的标签/整数吗?
  • @FabianSchultz:真的吗?这也适用于自定义 React 元素吗?上次我尝试时,我遇到了一个编译错误,导致我在下面的答案中使用了其中一种解决方案......
  • @FabianSchultz:很酷的伙伴,很高兴知道。这似乎不适用于 user defined React 组件,即情况 (1) 我使用 this.state.assetType[0] 定义了 &lt;DragNDrop/&gt;&lt;MultipleChoice /&gt;&lt;MatchPairs /&gt;不渲染&lt;DragNDrop /&gt;
  • 是的,你必须传入组件(对象)本身,而不是字符串。

标签: javascript reactjs babeljs jsx


【解决方案1】:

关于动态 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 ElementNameStartsWithCapitalLetter = this.state.assetType[0];
           // ^ -- capital letter here, ensure this works when used in JSX
        return <ElementNameStartsWithCapitalLetter />;
    }
}

这是因为 User Defined JSX Components Must BE Capitalized



以前的解决方案:

使用 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 :)
}

【讨论】:

    猜你喜欢
    • 2020-09-11
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2015-05-04
    相关资源
    最近更新 更多