Javascript React/JSX动态组件名称

Javascript React/JSX动态组件名称,javascript,reactjs,react-jsx,Javascript,Reactjs,React Jsx,我正在尝试根据组件的类型动态渲染组件 例如: var type = "Example"; var ComponentName = type + "Component"; return <ComponentName />; // Returns <examplecomponent /> instead of <ExampleComponent /> var type=“示例”; var ComponentName=类型+“组件”; 返回; //返回而不是

我正在尝试根据组件的类型动态渲染组件

例如:

var type = "Example";
var ComponentName = type + "Component";
return <ComponentName />; 
// Returns <examplecomponent />  instead of <ExampleComponent />
var type=“示例”;
var ComponentName=类型+“组件”;
返回;
//返回而不是
我尝试了这里提出的解决方案

这在编译时给了我一个错误(使用browserify进行gulp)。在我使用数组语法的地方,它需要XML

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

newExampleComponent() {
    return <ExampleComponent />;
}

newComponent(type) {
    return this["new" + type + "Component"]();
}
newExampleComponent(){
返回;
}
新成员(类型){
返回此[“新”+类型+“组件”]();
}
但这意味着我创建的每个组件都有一个新方法。对于这个问题,必须有一个更优雅的解决方案


我很乐意接受建议。

我想出了一个新的解决方案。请注意,我正在使用ES6模块,因此我需要该类。您还可以定义一个新的React类

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

var type = "example";

newComponent() {
    return components[type]({ attribute: "value" });
}
编译为
React.createElement(MyComponent,{})
,它需要字符串(HTML标记)或函数(ReactClass)作为第一个参数

您可以将组件类存储在一个名称以大写字母开头的变量中。看


如果您的组件是全局的,您只需执行以下操作:
var nameOfComponent=“SomeComponent”;

createElement(窗口[nameOfComponent],{})我使用了一种有点不同的方法,因为我们总是知道我们的实际组件,所以我想应用switch case。 在我的案例中,组件的总数量大约为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} />

    }
  }
getSubComponent(名称){
让customProps={
“第1项建议”:“,
“第二项建议”:“第二项建议”,
“第三项建议”:“第三项建议”,
“prop4”:”
}
交换机(名称){
案例“组件1”:返回
案例“组件2”:返回
案例“组件3”:返回
}
}

编辑:其他答案更好,请参见注释

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

...
render : function () {
  var componentToRender = 'component1Name';
  var componentLookup = {
    component1Name : (<Component1 />),
    component2Name : (<Component2 />),
    ...
  };
  return (<div>
    {componentLookup[componentToRender]}
  </div>);
}
...
。。。
渲染:函数(){
var componentorender='component1Name';
变量组件查找={
组件1名称:(),
组件2名称:(),
...
};
返回(
{componentLookup[componentToRender]}
);
}
...

对于包装器组件,一个简单的解决方案是直接使用
React.createElement
(使用ES6)


有关如何处理此类情况的官方文件可在此处查阅:

基本上它说:

错:

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} />;
}
从“React”导入React;
从“/stories”导入{PhotoStory,VideoStory};
常数分量={
照片:PhotoStory,
录像:录像故事
};
功能故事(道具){
//错误!JSX类型不能是表达式。
返回;
}
正确:

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} />;
}
从“React”导入React;
从“/stories”导入{PhotoStory,VideoStory};
常数分量={
照片:PhotoStory,
录像:录像故事
};
功能故事(道具){
//正确!JSX类型可以是大写的变量。
const SpecificStory=组件[props.storyType];
返回;
}

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

假设我们希望使用以下url路径访问具有两个唯一视图的页面“snozberrys”:

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

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

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'));
var componentName = "StringThatContainsComponentName";
const importedComponentModule = require("path/to/component/" + componentName).default;
return React.createElement(importedComponentModule); 
import React,{Component}来自'React';
从“react dom”导入react dom
进口{
BrowserRouter作为路由器,
路线
}从“反应路由器dom”
从“./AComponent.js”导入组件;
从“/BComponent.js”导入组件;
常量视图={
A成分:,
慰问:
}
常量视图=(道具)=>{
让name=props.location.search.substr(1);
让视图=视图[名称];
如果(view==null)抛出“view'”+name+“'未定义”;
返回视图;
}
类ViewManager扩展组件{
render(){
返回(
);
}
}
导出默认视图管理器
ReactDOM.render(,document.getElementById('root'));

应该有一个容器,将组件名称映射到应该动态使用的所有组件。组件类应该在容器中注册,因为在模块化环境中,并没有一个地方可以访问它们。组件类在未明确指定的情况下无法通过其名称进行标识,因为函数
name
在生产中已缩小

组件映射 它可以是普通对象:

class Foo extends React.Component { ... }
...
const componentsMap = { Foo, Bar };
...
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;
普通对象更合适,因为它得益于属性速记

桶模块 具有命名导出的映射可以充当以下映射:

// 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/>;
装饰器可以用作具有功能组件的高阶组件:

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

export default dynamic(Bar);

使用代替随机属性也有利于调试。

假设我们有一个
标志
,与
状态
道具
没有区别:

import ComponentOne from './ComponentOne';
import ComponentTwo from './ComponentTwo';

~~~

const Compo = flag ? ComponentOne : ComponentTwo;

~~~

<Compo someProp={someValue} />
import ComponentOne from./ComponentOne';
从“./ComponentTwo”导入ComponentTwo;
~~~
const Compo=标志?组件一:组件二;
~~~

使用flag
Component
填充
ComponentOne
ComponentTwo
中的一个,然后
Component
可以像React组件一样工作。

在组件映射的所有选项中,我还没有找到使用ES6短语法定义映射的最简单方法:

从“React”导入React
从“/stories”导入{PhotoStory,VideoStory}
常数分量={
摄影记录,
录像故事,
}
功能故事(道具){
//鉴于props.story包含“PhotoStory”或“VideoStory”
const SpecificStory=组件[props.story]
返回
}

拥有一张地图,有大量的组件,看起来一点都不好。事实上,我很惊讶没有人提出这样的建议:

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'));
var componentName = "StringThatContainsComponentName";
const importedComponentModule = require("path/to/component/" + componentName).default;
return React.createElement(importedComponentModule); 
当我需要以json数组的形式呈现大量加载的组件时,这一点确实帮助了我。

随着的介绍,我们现在可以使用真正的动态方法导入组件并重新加载
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);
import ComponentOne from './ComponentOne';
import ComponentTwo from './ComponentTwo';

~~~

const Compo = flag ? ComponentOne : ComponentTwo;

~~~

<Compo someProp={someValue} />
var componentName = "StringThatContainsComponentName";
const importedComponentModule = require("path/to/component/" + componentName).default;
return React.createElement(importedComponentModule); 
import React, { lazy, Suspense } from 'react';

const App = ({ componentName, ...props }) => {
  const DynamicComponent = lazy(() => import(`./${componentName}`));
    
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <DynamicComponent {...props} />
    </Suspense>
  );
};