我试图根据组件的类型动态呈现组件。

例如:

var type = "Example";
var ComponentName = type + "Component";
return <ComponentName />; 
// Returns <examplecomponent />  instead of <ExampleComponent />

我尝试了这里提出的React/JSX动态组件名称的解决方案

这在编译时给了我一个错误(使用browserify for gulp)。当我使用数组语法时,它期望XML。

我可以通过为每个组件创建一个方法来解决这个问题:

newExampleComponent() {
    return <ExampleComponent />;
}

newComponent(type) {
    return this["new" + type + "Component"]();
}

但这意味着我创建的每个组件都有一个新方法。这个问题一定有更优雅的解决办法。

我很愿意接受建议。

编辑: 正如gmfvpereira最近指出的,有一个官方文档条目: https://reactjs.org/docs/jsx-in-depth.html#choosing-the-type-at-runtime


当前回答

我使用了一点不同的方法,因为我们总是知道我们的实际组件,所以我认为应用开关情况。 另外,在我的案例中,组件总数在7-8左右。

getSubComponent(name) {
    let customProps = {
       "prop1" :"",
       "prop2":"",
       "prop3":"",
       "prop4":""
    }

    switch (name) {
      case "Component1": return <Component1 {...this.props} {...customProps} />
      case "Component2": return <Component2 {...this.props} {...customProps} />
      case "component3": return <component3 {...this.props} {...customProps} />

    }
  }

其他回答

我使用了一点不同的方法,因为我们总是知道我们的实际组件,所以我认为应用开关情况。 另外,在我的案例中,组件总数在7-8左右。

getSubComponent(name) {
    let customProps = {
       "prop1" :"",
       "prop2":"",
       "prop3":"",
       "prop4":""
    }

    switch (name) {
      case "Component1": return <Component1 {...this.props} {...customProps} />
      case "Component2": return <Component2 {...this.props} {...customProps} />
      case "component3": return <component3 {...this.props} {...customProps} />

    }
  }

我想出了一个新的解决办法。请注意,我使用ES6模块,所以我需要类。你也可以定义一个新的React类。

var components = {
    example: React.createFactory( require('./ExampleComponent') )
};

var type = "example";

newComponent() {
    return components[type]({ attribute: "value" });
}

假设我们希望通过动态组件加载访问各种视图。下面的代码给出了一个工作示例,说明如何通过使用从url的搜索字符串解析出来的字符串来实现这一点。

让我们假设我们想要访问一个页面'snozberrys'有两个独特的视图使用这些url路径:

'http://localhost:3000/snozberrys?aComponent'

and

'http://localhost:3000/snozberrys?bComponent'

我们像这样定义视图控制器:

import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import {
  BrowserRouter as Router,
  Route
} from 'react-router-dom'
import AComponent from './AComponent.js';
import CoBComponent sole from './BComponent.js';

const views = {
  aComponent: <AComponent />,
  console: <BComponent />
}

const View = (props) => {
  let name = props.location.search.substr(1);
  let view = views[name];
  if(view == null) throw "View '" + name + "' is undefined";
  return view;
}

class ViewManager extends Component {
  render() {
    return (
      <Router>
        <div>
          <Route path='/' component={View}/>
        </div>
      </Router>
    );
  }
}

export default ViewManager

ReactDOM.render(<ViewManager />, document.getElementById('root'));

关于如何处理这种情况的官方文档可以在这里找到:https://facebook.github.io/react/docs/jsx-in-depth.html#choosing-the-type-at-runtime

基本上它说:

错误的:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
    photo: PhotoStory,
    video: VideoStory
};

function Story(props) {
    // Wrong! JSX type can't be an expression.
    return <components[props.storyType] story={props.story} />;
}

正确的:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
    photo: PhotoStory,
    video: VideoStory
};

function Story(props) {
    // Correct! JSX type can be a capitalized variable.
    const SpecificStory = components[props.storyType];
    return <SpecificStory story={props.story} />;
}

<MyComponent />编译为React。createElement(MyComponent,{}),它需要一个字符串(HTML标签)或一个函数(ReactClass)作为第一个参数。

您可以将组件类存储在一个名称以大写字母开头的变量中。参见HTML标签vs React组件。

var MyComponent = Components[type + "Component"];
return <MyComponent />;

编译,

var MyComponent = Components[type + "Component"];
return React.createElement(MyComponent, {});