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

例如:

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


当前回答

<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, {});

其他回答

关于如何处理这种情况的官方文档可以在这里找到: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} />;
}

我使用了一点不同的方法,因为我们总是知道我们的实际组件,所以我认为应用开关情况。 另外,在我的案例中,组件总数在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} />

    }
  }

应该有一个容器将组件名称映射到所有应该动态使用的组件。组件类应该注册在容器中,因为在模块化环境中,没有单独的地方可以访问它们。如果不显式地指定组件类,就不能通过它们的名称来标识它们,因为在生产环境中函数名被简化了。

组件图

它可以是plain object:

class Foo extends React.Component { ... }
...
const componentsMap = { Foo, Bar };
...
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;

或Map实例:

const componentsMap = new Map([[Foo, Foo], [Bar, Bar]]);
...
const DynamicComponent = componentsMap.get(componentName);

普通对象更适合,因为它受益于属性简写。

桶模块

具有命名exports的桶模块可以充当这样的map:

// Foo.js
export class Foo extends React.Component { ... }

// dynamic-components.js
export * from './Foo';
export * from './Bar';

// some module that uses dynamic component
import * as componentsMap from './dynamic-components';

const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;

如果每个模块代码风格有一个类,效果会很好。

装饰

装饰器可以用于类组件的语法糖,这仍然需要显式地指定类名并将它们注册到map中:

const componentsMap = {};

function dynamic(Component) {
  if (!Component.displayName)
    throw new Error('no name');

  componentsMap[Component.displayName] = Component;

  return Component;
}

...

@dynamic
class Foo extends React.Component {
  static displayName = 'Foo'
  ...
}

装饰器可以作为功能组件的高阶组件使用:

const Bar = props => ...;
Bar.displayName = 'Bar';

export default dynamic(Bar);

使用非标准的displayName而不是random属性也有利于调试。

如果你的组件是全局的,你可以简单地这样做: var nameOfComponent = " someecomponent "; 反应。createElement(窗口(nameOfComponent), {});

编辑:其他答案更好,见评论。

我用这种方法解决了同样的问题:

...
render : function () {
  var componentToRender = 'component1Name';
  var componentLookup = {
    component1Name : (<Component1 />),
    component2Name : (<Component2 />),
    ...
  };
  return (<div>
    {componentLookup[componentToRender]}
  </div>);
}
...