我试图根据组件的类型动态呈现组件。
例如:
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
关于如何处理这种情况的官方文档可以在这里找到: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} />;
}
随着React的引入。Lazy,我们现在可以使用真正的动态方法来导入组件并渲染它。
import React, { lazy, Suspense } from 'react';
const App = ({ componentName, ...props }) => {
const DynamicComponent = lazy(() => import(`./${componentName}`));
return (
<Suspense fallback={<div>Loading...</div>}>
<DynamicComponent {...props} />
</Suspense>
);
};
当然,这种方法对文件层次结构做了一些假设,并且可以使代码很容易被破坏。
假设你能够像这样从组件中导出*…
// src/components/index.js
export * from './Home'
export * from './Settings'
export * from './SiteList'
然后你可以重新导入*到一个新的comps对象中,然后它可以用来访问你的模块。
// src/components/DynamicLoader.js
import React from 'react'
import * as comps from 'components'
export default function ({component, defaultProps}) {
const DynamicComponent = comps[component]
return <DynamicComponent {...defaultProps} />
}
只需传入一个字符串值,该值标识您想要绘制的组件,以及需要绘制组件的位置。
<DynamicLoader component='Home' defaultProps={someProps} />