从字符串创建React类的实例

ewa*_*wan 19 class dynamic instance reactjs

我有一个字符串,其中包含类的名称(这来自一个json文件).这个字符串告诉我的Template Class哪个布局/模板用于数据(也在json中).问题是我的布局没有显示.

Home.jsx:

//a template or layout.
var Home = React.createClass({
  render () {
    return (
    <div>Home layout</div>
    )
  }
});
Run Code Online (Sandbox Code Playgroud)

Template.jsx:

var Template = React.createClass({
  render: function() {
    var Tag = this.props.template; //this is the name of the class eg. 'Home'
    return (
        <Tag />
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

我没有得到任何错误,但我也没有看到布局/ Home Class.我检查了props.template,这会记录正确的信息.此外,我可以在DOM中看到home元素.但它看起来像这样:

<div id='template-holder>
    <home></home>
</div>
Run Code Online (Sandbox Code Playgroud)

如果我将以下行更改为:

var Tag = Home;
//this works but it's not dynamic!
Run Code Online (Sandbox Code Playgroud)

任何想法,我如何解决这个问题?我确定它要么是简单的修复,要么是我做了一些愚蠢的事情.帮助将不胜感激.如果已经有人问过这个道歉(我找不到).

谢谢,Ewan

Mic*_*ley 17

这不起作用:

var Home = React.createClass({ ... });

var Component = "Home";
React.render(<Component />, ...);
Run Code Online (Sandbox Code Playgroud)

但是,这将:

var Home = React.createClass({ ... });

var Component = Home;
React.render(<Component />, ...);
Run Code Online (Sandbox Code Playgroud)

所以你只需要找到一种在字符串 "Home"组件类 之间进行映射的方法Home.一个简单的对象将作为基本注册表工作,如果您需要更多功能,可以从那里构建.

var components = {
  "Home": Home,
  "Other": OtherComponent
};

var Component = components[this.props.template];
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,我希望避免在代码中有地图/链接.我希望能够在不更改主代码库的情况下添加模板.这不可能吗? (2认同)
  • 太棒了@MichelleTilley!我的 linter 甚至简化为 `var Components = { Home, Other, };` 并且工作得很好。 (2认同)

Rob*_*kal 8

如果您可以将所有组件放在一个模块中,那么无需手动将类映射到字典即可实现:

   import * as widgets from 'widgets';
   var Type = widgets[this.props.template];
   ...
   <Type />
Run Code Online (Sandbox Code Playgroud)

通配符import语句已经是字典,代码的工作方式与上一个答案中的注册表类似.

实际上,我认为你可以使用一个额外的映射来处理多个模块:

import * as widgets from 'widgets';
import * as widgets2 from 'widgets2';

const registry = Object.assign({}, widgets, widgets2);
const widget = registry[this.props.template];
Run Code Online (Sandbox Code Playgroud)

我完全会这样做.事实上我认为我是.


小智 5

我遇到了同样的问题,并自己找到了解决方案。我不知道是否是“最佳实践”,但它有效,我目前在我的解决方案中使用它。

您可以简单地使用“evil” eval 函数来动态创建 React 组件的实例。就像是:

function createComponent(componentName, props, children){
  var component = React.createElement(eval(componentName), props, children);
  return component;
}
Run Code Online (Sandbox Code Playgroud)

然后,只需在您想要的地方调用它:

var homeComponent = createComponent('Home', [props], [...children]);
Run Code Online (Sandbox Code Playgroud)

如果它符合您的需求,也许您可​​以考虑这样的事情。

希望能帮助到你。

  • 除非用户可以输入他们想要的任何内容,否则我不会认为 `eval` 是邪恶的。 (3认同)