我试图根据组件的类型动态呈现组件。
例如:
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
假设我们希望通过动态组件加载访问各种视图。下面的代码给出了一个工作示例,说明如何通过使用从url的搜索字符串解析出来的字符串来实现这一点。
让我们假设我们想要访问一个页面'snozberrys'有两个独特的视图使用这些url路径:
'http://localhost:3000/snozberrys?aComponent'
and
'http://localhost:3000/snozberrys?bComponent'
我们像这样定义视图控制器:
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'));
关于如何处理这种情况的官方文档可以在这里找到: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。直接createElement(使用ES6)。
import RaisedButton from 'mui/RaisedButton'
import FlatButton from 'mui/FlatButton'
import IconButton from 'mui/IconButton'
class Button extends React.Component {
render() {
const { type, ...props } = this.props
let button = null
switch (type) {
case 'flat': button = FlatButton
break
case 'icon': button = IconButton
break
default: button = RaisedButton
break
}
return (
React.createElement(button, { ...props, disableTouchRipple: true, disableFocusRipple: true })
)
}
}