React / JSX 动态组件名称

IT技术 javascript reactjs react-jsx
2021-02-08 18:22:21

我正在尝试根据组件的类型动态呈现组件。

例如:

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"]();
}

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

我很乐意接受建议。

6个回答

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

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

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

编译为

var MyComponent = Components[type + "Component"];
return React.createElement(MyComponent, {});
如果您还想知道为什么var 需要大写facebook.github.io/react/docs/...
2021-03-16 18:22:21
组件未定义
2021-03-22 18:22:21
未来的读者也可能会发现{...this.props}将 props 透明地从父级传递给子类型组件很有用。喜欢return <MyComponent {...this.props} />
2021-03-24 18:22:21
还要确保将动态变量名称大写。
2021-04-04 18:22:21
请记住,您的变量应该保存组件本身,不仅仅是作为字符串的组件名称
2021-04-04 18:22:21

这里有一份关于如何处理这种情况的官方文档: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} />;
}
非常重要的事情:一个大写的变量
2021-03-30 18:22:21
谢谢你的好回答。下面的读者请注意,map对象内的值(这里的map对象为const组件,值为PhotoStory和VideoStory)必须不带引号——否则组件不渲染会报错——在我的万一我错过了,只是浪费时间......
2021-04-08 18:22:21

应该有一个容器将组件名称映射到所有应该动态使用的组件。组件类应该在容器中注册,因为在module化环境中,否则没有可以访问它们的单一位置。组件类不能在没有明确指定的情况下通过它们的名称来识别,因为功能name在生产中被缩小了。

组件图

它可以是普通对象:

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);

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

枪管module

筒module与命名出口可以充当这样的地图:

// 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/>;

这适用于每个module代码样式的一个类。

装饰器

装饰器可以与类组件一起使用以获得语法糖,这仍然需要明确指定类名并将它们注册到映射中:

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而不是随机属性也有利于调试。

我想出了一个新的解决方案。请注意,我使用的是 ES6 module,因此我需要该类。你也可以定义一个新的 React 类。

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

var type = "example";

newComponent() {
    return components[type]({ attribute: "value" });
}
@klinore 您是否尝试访问该default属性?即:需要('./ExampleComponent')。默认?
2021-04-05 18:22:21

如果您的组件是全局的,您可以简单地执行以下操作:

var nameOfComponent = "SomeComponent";
React.createElement(window[nameOfComponent], {});

这很好用,尤其是在使用 Rails 时。接受的答案对我不起作用,因为Components未定义数组。
2021-03-12 18:22:21
与其将任意命名的对象附加到全局范围 (euw),您应该考虑维护一个组件注册表,您可以注册该注册表,然后在需要时从中检索组件引用。
2021-03-18 18:22:21