【问题标题】:React Dynamic tag name反应动态标签名称
【发布时间】:2016-08-03 08:27:00
【问题描述】:

假设以下和所有组件/fus/fci/ssg 只有一个带有站点道具的 h1。我想了解为什么它是一个有效的反应元素,但这些元素并没有显示同样的渲染。也就是说,一个有 h1 元素,另一个没有。这个想法是不要为不同的站点创建带有切换的大型组件,并且每个站点都将根据导航选择进行交换。除非我错过了,否则我没有看到任何记录...

{this.state.renderSite}
<Fci site="Fci"/>

import React from 'react';                                                 
import styles from './App.css';                                            
import Nav from '../components/Nav.js'                                     
import Fus from '../components/Fus.js'                                     
import Fci from '../components/Fci.js'                                     
import Ssg from '../components/Ssg.js'                                     

export default class App extends React.Component {                         
  constructor(props) {                                                     
    super(props);                                                          
    this.state = {renderSite: '', site: 'default' };                       
    this.pickSite = this.pickSite.bind(this);                              
  }                                                                        

  pickSite(site){                                                          
    this.setState({renderSite: React.createElement(site, {"site":site})}); 
    this.setState({site: site});                                           
    console.log( React.isValidElement(this.state.renderSite));             
}                                                                          

  render() {                                                               
    return (                                                               
      <div className={styles.app}>                                         
      <Nav site={this.pickSite.bind(this)} /> 
      {this.state.renderSite}                  
      <Fci site="Fci"/>                                                    
      </div>                                                               
    );                                                                     
  }                                                                        
}                                                                          

导航

import React from 'react';

export default class Nav extends React.Component {
        constructor(props) {
            super(props);
            this.update = this.update.bind(this);
        }

        update(e) {
           this.props.site(e.target.dataset.site);
        }

        render(){ 
            return ( 
                <div>
                    <button onClick={this.update} data-site="Ssg"> SSG </button>
                    <button onClick={this.update} data-site="Fci"> FCI </button>
                    <button onClick={this.update} data-site="Fus"> FUS </button>
                </div>
                     );
        }       
}

【问题讨论】:

  • 你能发布Nav组件吗?
  • @Aaron 添加了导航组件

标签: dynamic reactjs components


【解决方案1】:

问题在于,当您创建元素时,您传递的是字符串(data-site 值),而不是组件引用。所以它最终是这样的:

React.createElement("Fci");

相对于:

React.createElement(Fci);

使用字符串将创建一个简单的 HTML 元素,而不是具有自己渲染内容的组件。

你可以像这样创建一个组件映射:

const componentMap = {
    "Fci": Fci,
    "Fus": Fus,
    "Ssg": Ssg
}

然后你可以从你的字符串中解析一个组件引用:

React.createElement(componentMap[site], {site: site});

或者您可以从Nav 传递组件引用:

<button onClick={this.update.bind(this, Ssg, "Ssg"}> SSG </button>

update(component, site, e) {
    this.props.site(component, site);
}

pickSite(component, site) {
    React.createElement(component, {site: site});
}

【讨论】:

  • 好发现!顺便说一句,与其创建元素并将(对)创建元素的(引用)完全存储在状态中,我建议仅将对组件的引用存储在您的状态中,并在您的渲染函数中创建实际元素。让你的代码更干净
  • 我同意@wintvelt 的观点,事实上我会尽可能只将字符串存储在状态中,并在您的render 函数中进行所有元素映射和创建。你可以创建一个像renderSite() 这样的子渲染函数来隔离它。
  • @Aaron 我不喜欢在渲染中将 jsx 与 js 内部混合的想法;但是,假设状态很好,相同的 会因意外令牌而失败。混合是否正常,为什么 createElement 在这种情况下有效,而不是 jsx?
  • 请参阅stackoverflow.com/a/33471928/567525 了解避免createElement() 的更简单方法
  • @jbustamovej 该方法在这种情况下不起作用,因为Fci 是一个组件而不是一个html 标签
猜你喜欢
  • 1970-01-01
  • 2017-05-28
  • 2015-03-27
  • 2020-09-11
  • 1970-01-01
  • 2019-02-05
  • 1970-01-01
相关资源
最近更新 更多